diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index b8cf72c2c73ff..325342d653dd2 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1612,10 +1612,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .any(|impl_def_id| { let impl_header = tcx.impl_trait_header(impl_def_id); impl_header.is_some_and(|header| { - let header = header.instantiate( + let trait_ref = header.trait_ref.instantiate( tcx, infcx.fresh_args_for_item(DUMMY_SP, impl_def_id), ); + let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased); // FIXME: Don't bother dealing with non-lifetime binders here... if value.has_escaping_bound_vars() { @@ -1624,7 +1625,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { infcx .can_eq( ty::ParamEnv::empty(), - header.trait_ref.self_ty(), + trait_ref.self_ty(), value, ) && header.polarity != ty::ImplPolarity::Negative }) @@ -1677,9 +1678,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .filter(|header| { // Consider only accessible traits tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx) - && header.skip_binder().polarity != ty::ImplPolarity::Negative + && header.polarity != ty::ImplPolarity::Negative }) - .map(|header| header.instantiate_identity().trait_ref.self_ty()) + .map(|header| header.trait_ref.instantiate_identity().self_ty()) // We don't care about blanket impls. .filter(|self_ty| !self_ty.has_non_region_param()) .map(|self_ty| tcx.erase_regions(self_ty).to_string()) diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 7705445ffaa42..b9543c7a29b2a 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -45,10 +45,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { dummy_self, &mut bounds, false, - // FIXME: This should be `true`, but we don't really handle - // associated type bounds or type aliases in objects in a way - // that makes this meaningful, I think. - OnlySelfBounds(false), + // True so we don't populate `bounds` with associated type bounds, even + // though they're disallowed from object types. + OnlySelfBounds(true), ) { potential_assoc_types.extend(cur_potential_assoc_types); } @@ -83,9 +82,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let expanded_traits = traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b))); - let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits - .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self) - .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); + let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = + expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); if regular_traits.len() > 1 { let first_trait = ®ular_traits[0]; let additional_trait = ®ular_traits[1]; @@ -158,7 +156,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { for (base_trait_ref, span) in regular_traits_refs_spans { let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx); - for pred in traits::elaborate(tcx, [base_pred]) { + for pred in traits::elaborate(tcx, [base_pred]).filter_only_self() { debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred); let bound_predicate = pred.kind(); @@ -312,45 +310,39 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) }); - let existential_projections = projection_bounds - .iter() - // We filter out traits that don't have `Self` as their self type above, - // we need to do the same for projections. - .filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self) - .map(|(bound, _)| { - bound.map_bound(|mut b| { - assert_eq!(b.projection_ty.self_ty(), dummy_self); + let existential_projections = projection_bounds.iter().map(|(bound, _)| { + bound.map_bound(|mut b| { + assert_eq!(b.projection_ty.self_ty(), dummy_self); - // Like for trait refs, verify that `dummy_self` did not leak inside default type - // parameters. - let references_self = b.projection_ty.args.iter().skip(1).any(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return true; - } - false - }); - if references_self { - let guar = tcx.dcx().span_delayed_bug( - span, - "trait object projection bounds reference `Self`", - ); - let args: Vec<_> = b - .projection_ty - .args - .iter() - .map(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return Ty::new_error(tcx, guar).into(); - } - arg - }) - .collect(); - b.projection_ty.args = tcx.mk_args(&args); + // Like for trait refs, verify that `dummy_self` did not leak inside default type + // parameters. + let references_self = b.projection_ty.args.iter().skip(1).any(|arg| { + if arg.walk().any(|arg| arg == dummy_self.into()) { + return true; } + false + }); + if references_self { + let guar = tcx + .dcx() + .span_delayed_bug(span, "trait object projection bounds reference `Self`"); + let args: Vec<_> = b + .projection_ty + .args + .iter() + .map(|arg| { + if arg.walk().any(|arg| arg == dummy_self.into()) { + return Ty::new_error(tcx, guar).into(); + } + arg + }) + .collect(); + b.projection_ty.args = tcx.mk_args(&args); + } - ty::ExistentialProjection::erase_self_ty(tcx, b) - }) - }); + ty::ExistentialProjection::erase_self_ty(tcx, b) + }) + }); let regular_trait_predicates = existential_trait_refs .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 845bbdca96aba..748571c12b3df 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -530,11 +530,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { } DefKind::Impl { of_trait } => { if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) { - check_impl_items_against_trait( - tcx, - def_id, - impl_trait_header.instantiate_identity(), - ); + check_impl_items_against_trait(tcx, def_id, impl_trait_header); check_on_unimplemented(tcx, def_id); } } @@ -725,10 +721,11 @@ fn check_impl_items_against_trait<'tcx>( impl_id: LocalDefId, impl_trait_header: ty::ImplTraitHeader<'tcx>, ) { + let trait_ref = impl_trait_header.trait_ref.instantiate_identity(); // If the trait reference itself is erroneous (so the compilation is going // to fail), skip checking the items here -- the `impl_item` table in `tcx` // isn't populated for such impls. - if impl_trait_header.references_error() { + if trait_ref.references_error() { return; } @@ -752,7 +749,7 @@ fn check_impl_items_against_trait<'tcx>( } } - let trait_def = tcx.trait_def(impl_trait_header.trait_ref.def_id); + let trait_def = tcx.trait_def(trait_ref.def_id); for &impl_item in impl_item_refs { let ty_impl_item = tcx.associated_item(impl_item); @@ -771,10 +768,10 @@ fn check_impl_items_against_trait<'tcx>( )); } ty::AssocKind::Fn => { - compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref); + compare_impl_method(tcx, ty_impl_item, ty_trait_item, trait_ref); } ty::AssocKind::Type => { - compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref); + compare_impl_ty(tcx, ty_impl_item, ty_trait_item, trait_ref); } } @@ -794,7 +791,7 @@ fn check_impl_items_against_trait<'tcx>( let mut must_implement_one_of: Option<&[Ident]> = trait_def.must_implement_one_of.as_deref(); - for &trait_item_id in tcx.associated_item_def_ids(impl_trait_header.trait_ref.def_id) { + for &trait_item_id in tcx.associated_item_def_ids(trait_ref.def_id) { let leaf_def = ancestors.leaf_def(tcx, trait_item_id); let is_implemented = leaf_def @@ -872,7 +869,7 @@ fn check_impl_items_against_trait<'tcx>( if let Some(missing_items) = must_implement_one_of { let attr_span = tcx - .get_attr(impl_trait_header.trait_ref.def_id, sym::rustc_must_implement_one_of) + .get_attr(trait_ref.def_id, sym::rustc_must_implement_one_of) .map(|attr| attr.span); missing_items_must_implement_one_of_err( diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 8d457da89e8a8..ae7ea271c5669 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -247,7 +247,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() hir::ItemKind::Impl(impl_) => { let header = tcx.impl_trait_header(def_id); let is_auto = header - .is_some_and(|header| tcx.trait_is_auto(header.skip_binder().trait_ref.def_id)); + .is_some_and(|header| tcx.trait_is_auto(header.trait_ref.skip_binder().def_id)); crate::impl_wf_check::check_impl_wf(tcx, def_id)?; let mut res = Ok(()); @@ -261,7 +261,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() .emit()); } // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span. - match header.map(|h| h.skip_binder().polarity) { + match header.map(|h| h.polarity) { // `None` means this is an inherent impl Some(ty::ImplPolarity::Positive) | None => { res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait)); @@ -298,31 +298,31 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() hir::ItemKind::Const(ty, ..) => { check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid) } - hir::ItemKind::Struct(_, ast_generics) => { + hir::ItemKind::Struct(_, hir_generics) => { let res = check_type_defn(tcx, item, false); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Union(_, ast_generics) => { + hir::ItemKind::Union(_, hir_generics) => { let res = check_type_defn(tcx, item, true); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Enum(_, ast_generics) => { + hir::ItemKind::Enum(_, hir_generics) => { let res = check_type_defn(tcx, item, true); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } hir::ItemKind::Trait(..) => check_trait(tcx, item), hir::ItemKind::TraitAlias(..) => check_trait(tcx, item), // `ForeignItem`s are handled separately. hir::ItemKind::ForeignMod { .. } => Ok(()), - hir::ItemKind::TyAlias(hir_ty, ast_generics) => { + hir::ItemKind::TyAlias(hir_ty, hir_generics) => { if tcx.type_alias_is_lazy(item.owner_id) { // Bounds of lazy type aliases and of eager ones that contain opaque types are respected. // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`. let res = check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } else { Ok(()) @@ -1277,16 +1277,16 @@ fn check_item_type( }) } -#[instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))] +#[instrument(level = "debug", skip(tcx, hir_self_ty, hir_trait_ref))] fn check_impl<'tcx>( tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>, - ast_self_ty: &hir::Ty<'_>, - ast_trait_ref: &Option>, + hir_self_ty: &hir::Ty<'_>, + hir_trait_ref: &Option>, ) -> Result<(), ErrorGuaranteed> { enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| { - match ast_trait_ref { - Some(ast_trait_ref) => { + match hir_trait_ref { + Some(hir_trait_ref) => { // `#[rustc_reservation_impl]` impls are not real impls and // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). @@ -1294,8 +1294,9 @@ fn check_impl<'tcx>( // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. tcx.ensure().coherent_trait(trait_ref.def_id)?; + let trait_span = hir_trait_ref.path.span; let trait_ref = wfcx.normalize( - ast_trait_ref.path.span, + trait_span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), trait_ref, ); @@ -1306,14 +1307,23 @@ fn check_impl<'tcx>( wfcx.param_env, wfcx.body_def_id, trait_pred, - ast_trait_ref.path.span, + trait_span, item, ); for obligation in &mut obligations { + if obligation.cause.span != trait_span { + // We already have a better span. + continue; + } if let Some(pred) = obligation.predicate.to_opt_poly_trait_pred() - && pred.self_ty().skip_binder() == trait_ref.self_ty() + && pred.skip_binder().self_ty() == trait_ref.self_ty() + { + obligation.cause.span = hir_self_ty.span; + } + if let Some(pred) = obligation.predicate.to_opt_poly_projection_pred() + && pred.skip_binder().self_ty() == trait_ref.self_ty() { - obligation.cause.span = ast_self_ty.span; + obligation.cause.span = hir_self_ty.span; } } debug!(?obligations); @@ -1327,7 +1337,7 @@ fn check_impl<'tcx>( self_ty, ); wfcx.register_wf_obligation( - ast_self_ty.span, + hir_self_ty.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), self_ty.into(), ); diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 6c3a9b747ef61..8d8b13d6cb397 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -25,7 +25,7 @@ use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; use std::collections::BTreeMap; -pub fn check_trait<'tcx>( +pub(super) fn check_trait<'tcx>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, impl_def_id: LocalDefId, @@ -66,10 +66,9 @@ impl<'tcx> Checker<'tcx> { fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { let tcx = checker.tcx; - let header = checker.impl_header; let impl_did = checker.impl_def_id; // Destructors only work on local ADT types. - match header.trait_ref.self_ty().kind() { + match checker.impl_header.trait_ref.instantiate_identity().self_ty().kind() { ty::Adt(def, _) if def.did().is_local() => return Ok(()), ty::Error(_) => return Ok(()), _ => {} @@ -86,7 +85,7 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran let impl_did = checker.impl_def_id; debug!("visit_implementation_of_copy: impl_did={:?}", impl_did); - let self_type = impl_header.trait_ref.self_ty(); + let self_type = impl_header.trait_ref.instantiate_identity().self_ty(); debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type); let param_env = tcx.param_env(impl_did); @@ -120,7 +119,7 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E let tcx = checker.tcx; let header = checker.impl_header; let impl_did = checker.impl_def_id; - let self_type = header.trait_ref.self_ty(); + let self_type = header.trait_ref.instantiate_identity().self_ty(); assert!(!self_type.has_escaping_bound_vars()); let param_env = tcx.param_env(impl_did); @@ -157,9 +156,8 @@ fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), E fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { let tcx = checker.tcx; - let header = checker.impl_header; let impl_did = checker.impl_def_id; - let trait_ref = header.trait_ref; + let trait_ref = checker.impl_header.trait_ref.instantiate_identity(); debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did); let span = tcx.def_span(impl_did); diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index d6281fa08f745..fc7a73e12be0a 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -134,11 +134,12 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> let mut res = tcx.ensure().specialization_graph_of(def_id); for &impl_def_id in impls { - let trait_header = tcx.impl_trait_header(impl_def_id).unwrap().instantiate_identity(); - let trait_def = tcx.trait_def(trait_header.trait_ref.def_id); + let trait_header = tcx.impl_trait_header(impl_def_id).unwrap(); + let trait_ref = trait_header.trait_ref.instantiate_identity(); + let trait_def = tcx.trait_def(trait_ref.def_id); - res = res.and(check_impl(tcx, impl_def_id, trait_header.trait_ref, trait_def)); - res = res.and(check_object_overlap(tcx, impl_def_id, trait_header.trait_ref)); + res = res.and(check_impl(tcx, impl_def_id, trait_ref, trait_def)); + res = res.and(check_object_overlap(tcx, impl_def_id, trait_ref)); res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def)); res = res.and(tcx.ensure().orphan_check_impl(impl_def_id)); diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 53a5ada410560..13ce4f0759377 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -13,9 +13,10 @@ pub(super) fn check_item( trait_header: ImplTraitHeader<'_>, trait_def: &TraitDef, ) -> Result<(), ErrorGuaranteed> { - let trait_ref = trait_header.trait_ref; let unsafe_attr = tcx.generics_of(def_id).params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); + let trait_ref = trait_header.trait_ref.instantiate_identity(); + match (trait_def.unsafety, unsafe_attr, trait_header.unsafety, trait_header.polarity) { (Unsafety::Normal, None, Unsafety::Unsafe, Positive | Reservation) => { let span = tcx.def_span(def_id); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 2cc37651ef521..e1704ffc8bfbf 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1519,10 +1519,7 @@ fn suggest_impl_trait<'tcx>( None } -fn impl_trait_header( - tcx: TyCtxt<'_>, - def_id: LocalDefId, -) -> Option>> { +fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option> { let icx = ItemCtxt::new(tcx, def_id); let item = tcx.hir().expect_item(def_id); let impl_ = item.expect_impl(); @@ -1558,11 +1555,11 @@ fn impl_trait_header( } else { icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty) }; - ty::EarlyBinder::bind(ty::ImplTraitHeader { - trait_ref, + ty::ImplTraitHeader { + trait_ref: ty::EarlyBinder::bind(trait_ref), unsafety: impl_.unsafety, polarity: polarity_of_impl(tcx, def_id, impl_, item.span) - }) + } }) } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 893b3f9534de9..7012f40e3499b 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3368,11 +3368,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "inherent impls can't be candidates, only trait impls can be", ) }) - .filter(|header| { - header.skip_binder().polarity == ty::ImplPolarity::Negative - }) + .filter(|header| header.polarity == ty::ImplPolarity::Negative) .any(|header| { - let imp = header.instantiate_identity().trait_ref; + let imp = header.trait_ref.instantiate_identity(); let imp_simp = simplify_type(self.tcx, imp.self_ty(), TreatParams::ForLookup); imp_simp.is_some_and(|s| s == simp_rcvr_ty) diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index f30e366c19850..cc0f00254ffd8 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -77,7 +77,7 @@ impl<'tcx> InferCtxt<'tcx> { // that name placeholders created in this function. Nested goals from type relations can // also contain placeholders created by this function. let value = self.enter_forall_and_leak_universe(forall); - debug!("?value"); + debug!(?value); f(value) } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 085e90260515b..61f0ab14e8c1c 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -686,6 +686,11 @@ pub fn create_global_ctxt<'tcx>( /// Runs the type-checking, region checking and other miscellaneous analysis /// passes on the crate. fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { + if tcx.sess.opts.unstable_opts.hir_stats { + rustc_passes::hir_stats::print_hir_stats(tcx); + } + + #[cfg(debug_assertions)] rustc_passes::hir_id_validator::check_crate(tcx); let sess = tcx.sess; diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 90e68a6b5b916..dcccace12b00a 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -1077,7 +1077,7 @@ impl CrateError { crate_rejections, }); } else { - dcx.emit_err(errors::CannotFindCrate { + let error = errors::CannotFindCrate { span, crate_name, add_info, @@ -1091,11 +1091,18 @@ impl CrateError { profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: locator.triple, is_ui_testing: sess.opts.unstable_opts.ui_testing, - }); + }; + // The diagnostic for missing core is very good, but it is followed by a lot of + // other diagnostics that do not add information. + if missing_core { + dcx.emit_fatal(error); + } else { + dcx.emit_err(error); + } } } CrateError::NotFound(crate_name) => { - dcx.emit_err(errors::CannotFindCrate { + let error = errors::CannotFindCrate { span, crate_name, add_info: String::new(), @@ -1105,7 +1112,14 @@ impl CrateError { profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: sess.opts.target_triple.clone(), is_ui_testing: sess.opts.unstable_opts.ui_testing, - }); + }; + // The diagnostic for missing core is very good, but it is followed by a lot of + // other diagnostics that do not add information. + if missing_core { + dcx.emit_fatal(error); + } else { + dcx.emit_err(error); + } } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 3866d6fec2d15..6e9cbfdcfee28 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1993,9 +1993,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if of_trait && let Some(header) = tcx.impl_trait_header(def_id) { record!(self.tables.impl_trait_header[def_id] <- header); - let trait_ref = header.map_bound(|h| h.trait_ref); - let trait_ref = trait_ref.instantiate_identity(); + let trait_ref = header.trait_ref.instantiate_identity(); let simplified_self_ty = fast_reject::simplify_type( self.tcx, trait_ref.self_ty(), diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 281666876066a..8aa31ef564f55 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -423,7 +423,7 @@ define_tables! { variances_of: Table>, fn_sig: Table>>>, codegen_fn_attrs: Table>, - impl_trait_header: Table>>>, + impl_trait_header: Table>>, const_param_default: Table>>>, object_lifetime_default: Table>, optimized_mir: Table>>, diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index d0711baa18160..33ee3371605ae 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -177,8 +177,8 @@ impl EraseType for Option> { type Result = [u8; size_of::>>()]; } -impl EraseType for Option>> { - type Result = [u8; size_of::>>>()]; +impl EraseType for Option> { + type Result = [u8; size_of::>>()]; } impl EraseType for Option>> { diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index a8c0c3999f289..0268c530c9ee2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -840,7 +840,7 @@ rustc_queries! { /// Given an `impl_id`, return the trait it implements along with some header information. /// Return `None` if this is an inherent impl. - query impl_trait_header(impl_id: DefId) -> Option>> { + query impl_trait_header(impl_id: DefId) -> Option> { desc { |tcx| "computing trait implemented by `{}`", tcx.def_path_str(impl_id) } cache_on_disk_if { impl_id.is_local() } separate_provide_extern diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4eec93532a246..da81b9dd37558 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2310,12 +2310,11 @@ impl<'tcx> TyCtxt<'tcx> { self, def_id: impl IntoQueryParam, ) -> Option>> { - Some(self.impl_trait_header(def_id)?.map_bound(|h| h.trait_ref)) + Some(self.impl_trait_header(def_id)?.trait_ref) } pub fn impl_polarity(self, def_id: impl IntoQueryParam) -> ty::ImplPolarity { - self.impl_trait_header(def_id) - .map_or(ty::ImplPolarity::Positive, |h| h.skip_binder().polarity) + self.impl_trait_header(def_id).map_or(ty::ImplPolarity::Positive, |h| h.polarity) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 0a38d379a5216..d9f7ece83e0c9 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -250,9 +250,9 @@ pub struct ImplHeader<'tcx> { pub predicates: Vec>, } -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, TyEncodable, TyDecodable, HashStable)] +#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub struct ImplTraitHeader<'tcx> { - pub trait_ref: ty::TraitRef<'tcx>, + pub trait_ref: ty::EarlyBinder>, pub polarity: ImplPolarity, pub unsafety: hir::Unsafety, } @@ -1624,12 +1624,15 @@ impl<'tcx> TyCtxt<'tcx> { def_id1: DefId, def_id2: DefId, ) -> Option { - let impl1 = self.impl_trait_header(def_id1).unwrap().instantiate_identity(); - let impl2 = self.impl_trait_header(def_id2).unwrap().instantiate_identity(); + let impl1 = self.impl_trait_header(def_id1).unwrap(); + let impl2 = self.impl_trait_header(def_id2).unwrap(); + + let trait_ref1 = impl1.trait_ref.skip_binder(); + let trait_ref2 = impl2.trait_ref.skip_binder(); // If either trait impl references an error, they're allowed to overlap, // as one of them essentially doesn't exist. - if impl1.references_error() || impl2.references_error() { + if trait_ref1.references_error() || trait_ref2.references_error() { return Some(ImplOverlapKind::Permitted { marker: false }); } @@ -1650,7 +1653,7 @@ impl<'tcx> TyCtxt<'tcx> { let is_marker_overlap = { let is_marker_impl = |trait_ref: TraitRef<'_>| -> bool { self.trait_def(trait_ref.def_id).is_marker }; - is_marker_impl(impl1.trait_ref) && is_marker_impl(impl2.trait_ref) + is_marker_impl(trait_ref1) && is_marker_impl(trait_ref2) }; if is_marker_overlap { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index b0cb9fa517fd0..37cce625c8ec4 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -1361,7 +1361,7 @@ fn create_mono_items_for_default_impls<'tcx>( return; }; - if matches!(impl_.skip_binder().polarity, ty::ImplPolarity::Negative) { + if matches!(impl_.polarity, ty::ImplPolarity::Negative) { return; } @@ -1385,7 +1385,7 @@ fn create_mono_items_for_default_impls<'tcx>( } }; let impl_args = GenericArgs::for_item(tcx, item.owner_id.to_def_id(), only_region_params); - let trait_ref = impl_.instantiate(tcx, impl_args).trait_ref; + let trait_ref = impl_.trait_ref.instantiate(tcx, impl_args); // Unlike 'lazy' monomorphization that begins by collecting items transitively // called by `main` or other global items, when eagerly monomorphizing impl diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 54854cd2da995..ea9c78ca34c08 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -787,13 +787,17 @@ impl<'a> Parser<'a> { let suggest_eq = if self.token.kind == token::Dot && let _ = self.bump() && let mut snapshot = self.create_snapshot_for_diagnostic() - && let Ok(_) = snapshot.parse_dot_suffix_expr( - colon_sp, - self.mk_expr_err( + && let Ok(_) = snapshot + .parse_dot_suffix_expr( colon_sp, - self.dcx().delayed_bug("error during `:` -> `=` recovery"), - ), - ) { + self.mk_expr_err( + colon_sp, + self.dcx() + .delayed_bug("error during `:` -> `=` recovery"), + ), + ) + .map_err(Diag::cancel) + { true } else if let Some(op) = self.check_assoc_op() && op.node.can_continue_expr_unambiguously() diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs index 02f56ecb10b57..dd6c116695784 100644 --- a/compiler/rustc_passes/src/hir_id_validator.rs +++ b/compiler/rustc_passes/src/hir_id_validator.rs @@ -1,38 +1,26 @@ use rustc_data_structures::sync::Lock; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; -use rustc_hir::intravisit; -use rustc_hir::{HirId, ItemLocalId}; +use rustc_hir::{intravisit, HirId, ItemLocalId}; use rustc_index::bit_set::GrowableBitSet; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; pub fn check_crate(tcx: TyCtxt<'_>) { - if tcx.sess.opts.unstable_opts.hir_stats { - crate::hir_stats::print_hir_stats(tcx); - } - - #[cfg(debug_assertions)] - { - let errors = Lock::new(Vec::new()); + let errors = Lock::new(Vec::new()); - tcx.hir().par_for_each_module(|module_id| { - let mut v = HirIdValidator { - tcx, - owner: None, - hir_ids_seen: Default::default(), - errors: &errors, - }; + tcx.hir().par_for_each_module(|module_id| { + let mut v = + HirIdValidator { tcx, owner: None, hir_ids_seen: Default::default(), errors: &errors }; - tcx.hir().visit_item_likes_in_module(module_id, &mut v); - }); + tcx.hir().visit_item_likes_in_module(module_id, &mut v); + }); - let errors = errors.into_inner(); + let errors = errors.into_inner(); - if !errors.is_empty() { - let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); - tcx.dcx().delayed_bug(message); - } + if !errors.is_empty() { + let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); + tcx.dcx().delayed_bug(message); } } @@ -90,7 +78,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { self.error(|| { format!( "ItemLocalIds not assigned densely in {pretty_owner}. \ - Max ItemLocalId = {max}, missing IDs = {missing_items:#?}; seen IDs = {seen_items:#?}" + Max ItemLocalId = {max}, missing IDs = {missing_items:#?}; seen IDs = {seen_items:#?}" ) }); } diff --git a/compiler/rustc_passes/src/lib.rs b/compiler/rustc_passes/src/lib.rs index 7227b185f4d3b..e03052bcfede8 100644 --- a/compiler/rustc_passes/src/lib.rs +++ b/compiler/rustc_passes/src/lib.rs @@ -28,6 +28,7 @@ mod debugger_visualizer; mod diagnostic_items; pub mod entry; mod errors; +#[cfg(debug_assertions)] pub mod hir_id_validator; pub mod hir_stats; mod lang_items; diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 248985715c267..ed839d14dc7a3 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -166,13 +166,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; if !drcx.args_may_unify( goal.predicate.trait_ref(tcx).args, - impl_trait_header.skip_binder().trait_ref.args, + impl_trait_header.trait_ref.skip_binder().args, ) { return Err(NoSolution); } // We have to ignore negative impls when projecting. - let impl_polarity = impl_trait_header.skip_binder().polarity; + let impl_polarity = impl_trait_header.polarity; match impl_polarity { ty::ImplPolarity::Negative => return Err(NoSolution), ty::ImplPolarity::Reservation => { @@ -183,7 +183,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| { let impl_args = ecx.fresh_args_for_item(impl_def_id); - let impl_trait_ref = impl_trait_header.instantiate(tcx, impl_args).trait_ref; + let impl_trait_ref = impl_trait_header.trait_ref.instantiate(tcx, impl_args); ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?; diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index 16febf05b60e9..281f5cc5685d6 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -47,14 +47,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup }; if !drcx.args_may_unify( goal.predicate.trait_ref.args, - impl_trait_header.skip_binder().trait_ref.args, + impl_trait_header.trait_ref.skip_binder().args, ) { return Err(NoSolution); } // An upper bound of the certainty of this goal, used to lower the certainty // of reservation impl to ambiguous during coherence. - let impl_polarity = impl_trait_header.skip_binder().polarity; + let impl_polarity = impl_trait_header.polarity; let maximal_certainty = match impl_polarity { ty::ImplPolarity::Positive | ty::ImplPolarity::Negative => { match impl_polarity == goal.predicate.polarity { @@ -70,7 +70,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> { ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| { let impl_args = ecx.fresh_args_for_item(impl_def_id); - let impl_trait_ref = impl_trait_header.instantiate(tcx, impl_args).trait_ref; + let impl_trait_ref = impl_trait_header.trait_ref.instantiate(tcx, impl_args); ecx.eq(goal.param_env, goal.predicate.trait_ref, impl_trait_ref)?; let where_clause_bounds = tcx diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 7a930937255b9..ac2b738d3b662 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -1431,45 +1431,64 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { #[extension(pub(super) trait InferCtxtPrivExt<'tcx>)] impl<'tcx> TypeErrCtxt<'_, 'tcx> { + fn can_match_trait( + &self, + goal: ty::TraitPredicate<'tcx>, + assumption: ty::PolyTraitPredicate<'tcx>, + ) -> bool { + if goal.polarity != assumption.polarity() { + return false; + } + + let trait_goal = goal.trait_ref; + let trait_assumption = self.instantiate_binder_with_fresh_vars( + DUMMY_SP, + infer::BoundRegionConversionTime::HigherRankedType, + assumption.to_poly_trait_ref(), + ); + + self.can_eq(ty::ParamEnv::empty(), trait_goal, trait_assumption) + } + + fn can_match_projection( + &self, + goal: ty::ProjectionPredicate<'tcx>, + assumption: ty::PolyProjectionPredicate<'tcx>, + ) -> bool { + let assumption = self.instantiate_binder_with_fresh_vars( + DUMMY_SP, + infer::BoundRegionConversionTime::HigherRankedType, + assumption, + ); + + let param_env = ty::ParamEnv::empty(); + self.can_eq(param_env, goal.projection_ty, assumption.projection_ty) + && self.can_eq(param_env, goal.term, assumption.term) + } + // returns if `cond` not occurring implies that `error` does not occur - i.e., that // `error` occurring implies that `cond` occurs. + #[instrument(level = "debug", skip(self), ret)] fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool { if cond == error { return true; } - // FIXME: It should be possible to deal with `ForAll` in a cleaner way. - let bound_error = error.kind(); - let (cond, error) = match (cond.kind().skip_binder(), bound_error.skip_binder()) { - ( - ty::PredicateKind::Clause(ty::ClauseKind::Trait(..)), - ty::PredicateKind::Clause(ty::ClauseKind::Trait(error)), - ) => (cond, bound_error.rebind(error)), - _ => { - // FIXME: make this work in other cases too. - return false; - } - }; - - for pred in elaborate(self.tcx, std::iter::once(cond)) { - let bound_predicate = pred.kind(); - if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(implication)) = - bound_predicate.skip_binder() - { - let error = error.to_poly_trait_ref(); - let implication = bound_predicate.rebind(implication.trait_ref); - // FIXME: I'm just not taking associated types at all here. - // Eventually I'll need to implement param-env-aware - // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. - let param_env = ty::ParamEnv::empty(); - if self.can_sub(param_env, error, implication) { - debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); - return true; - } - } + if let Some(error) = error.to_opt_poly_trait_pred() { + self.enter_forall(error, |error| { + elaborate(self.tcx, std::iter::once(cond)) + .filter_map(|implied| implied.to_opt_poly_trait_pred()) + .any(|implied| self.can_match_trait(error, implied)) + }) + } else if let Some(error) = error.to_opt_poly_projection_pred() { + self.enter_forall(error, |error| { + elaborate(self.tcx, std::iter::once(cond)) + .filter_map(|implied| implied.to_opt_poly_projection_pred()) + .any(|implied| self.can_match_projection(error, implied)) + }) + } else { + false } - - false } #[instrument(skip(self), level = "debug")] @@ -1888,13 +1907,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .tcx .all_impls(trait_pred.def_id()) .filter_map(|def_id| { - let imp = self.tcx.impl_trait_header(def_id).unwrap().skip_binder(); + let imp = self.tcx.impl_trait_header(def_id).unwrap(); if imp.polarity == ty::ImplPolarity::Negative || !self.tcx.is_user_visible_dep(def_id.krate) { return None; } - let imp = imp.trait_ref; + let imp = imp.trait_ref.skip_binder(); self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map( |similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id }, @@ -2078,12 +2097,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .all_impls(def_id) // Ignore automatically derived impls and `!Trait` impls. .filter_map(|def_id| self.tcx.impl_trait_header(def_id)) - .map(ty::EarlyBinder::instantiate_identity) - .filter(|header| { - header.polarity != ty::ImplPolarity::Negative - || self.tcx.is_automatically_derived(def_id) + .filter_map(|header| { + (header.polarity != ty::ImplPolarity::Negative + || self.tcx.is_automatically_derived(def_id)) + .then(|| header.trait_ref.instantiate_identity()) }) - .map(|header| header.trait_ref) .filter(|trait_ref| { let self_ty = trait_ref.self_ty(); // Avoid mentioning type parameters. 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 39f4ceda9f17a..66f740b761d32 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -562,7 +562,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // and so forth that we need to. let impl_trait_header = self.tcx().impl_trait_header(impl_def_id).unwrap(); if !drcx - .args_may_unify(obligation_args, impl_trait_header.skip_binder().trait_ref.args) + .args_may_unify(obligation_args, impl_trait_header.trait_ref.skip_binder().args) { return; } @@ -577,7 +577,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if self.reject_fn_ptr_impls( impl_def_id, obligation, - impl_trait_header.skip_binder().trait_ref.self_ty(), + impl_trait_header.trait_ref.skip_binder().self_ty(), ) { return; } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 7dbea0cdb90c9..a6bd1ba9c3f88 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -42,7 +42,7 @@ use rustc_middle::ty::_match::MatchAgainstFreshVars; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::GenericArgsRef; -use rustc_middle::ty::{self, EarlyBinder, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; +use rustc_middle::ty::{self, PolyProjectionPredicate, ToPolyTraitRef, ToPredicate}; use rustc_middle::ty::{Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::symbol::sym; use rustc_span::Symbol; @@ -2441,7 +2441,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { fn match_impl( &mut self, impl_def_id: DefId, - impl_trait_header: EarlyBinder>, + impl_trait_header: ty::ImplTraitHeader<'tcx>, obligation: &PolyTraitObligation<'tcx>, ) -> Result>, ()> { let placeholder_obligation = @@ -2450,8 +2450,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { let impl_args = self.infcx.fresh_args_for_item(obligation.cause.span, impl_def_id); - let impl_trait_header = impl_trait_header.instantiate(self.tcx(), impl_args); - if impl_trait_header.references_error() { + let trait_ref = impl_trait_header.trait_ref.instantiate(self.tcx(), impl_args); + if trait_ref.references_error() { return Err(()); } @@ -2464,7 +2464,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - impl_trait_header.trait_ref, + trait_ref, ) }); diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index f5bc6c3ad2c50..27dd8f26489e7 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -169,7 +169,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, } } - let impl1_trait_header = tcx.impl_trait_header(impl1_def_id).unwrap().instantiate_identity(); + let impl1_trait_header = tcx.impl_trait_header(impl1_def_id).unwrap(); // We determine whether there's a subset relationship by: // @@ -198,7 +198,7 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, fulfill_implication( &infcx, penv, - impl1_trait_header.trait_ref, + impl1_trait_header.trait_ref.instantiate_identity(), impl1_def_id, impl2_def_id, |_, _| ObligationCause::dummy(), diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 6e01e0b76aafa..3f433a9e919a3 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -127,7 +127,7 @@ impl<'tcx> TraitAliasExpander<'tcx> { } // Get components of trait alias. - let predicates = tcx.implied_predicates_of(trait_ref.def_id()); + let predicates = tcx.super_predicates_of(trait_ref.def_id()); debug!(?predicates); let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 15059bc661396..b09a803e856d2 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -223,60 +223,87 @@ enum Elaborate { None, } +/// Points the cause span of a super predicate at the relevant associated type. +/// +/// Given a trait impl item: +/// +/// ```ignore (incomplete) +/// impl TargetTrait for TargetType { +/// type Assoc = SomeType; +/// } +/// ``` +/// +/// And a super predicate of `TargetTrait` that has any of the following forms: +/// +/// 1. `::Assoc == ::Assoc` +/// 2. `<::Assoc as OtherTrait>::Assoc == OtherType` +/// 3. `::Assoc: OtherTrait` +/// +/// Replace the span of the cause with the span of the associated item: +/// +/// ```ignore (incomplete) +/// impl TargetTrait for TargetType { +/// type Assoc = SomeType; +/// // ^^^^^^^^ this span +/// } +/// ``` +/// +/// Note that bounds that can be expressed as associated item bounds are **not** +/// super predicates. This means that form 2 and 3 from above are only relevant if +/// the [`GenericArgsRef`] of the projection type are not its identity arguments. fn extend_cause_with_original_assoc_item_obligation<'tcx>( tcx: TyCtxt<'tcx>, - trait_ref: ty::TraitRef<'tcx>, item: Option<&hir::Item<'tcx>>, cause: &mut traits::ObligationCause<'tcx>, pred: ty::Predicate<'tcx>, ) { - debug!( - "extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}", - trait_ref, item, cause, pred - ); + debug!(?item, ?cause, ?pred, "extended_cause_with_original_assoc_item_obligation"); let (items, impl_def_id) = match item { Some(hir::Item { kind: hir::ItemKind::Impl(impl_), owner_id, .. }) => { (impl_.items, *owner_id) } _ => return, }; - let fix_span = - |impl_item_ref: &hir::ImplItemRef| match tcx.hir().impl_item(impl_item_ref.id).kind { - hir::ImplItemKind::Const(ty, _) | hir::ImplItemKind::Type(ty) => ty.span, - _ => impl_item_ref.span, - }; + + let ty_to_impl_span = |ty: Ty<'_>| { + if let ty::Alias(ty::Projection, projection_ty) = ty.kind() + && let Some(&impl_item_id) = + tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id) + && let Some(impl_item) = + items.iter().find(|item| item.id.owner_id.to_def_id() == impl_item_id) + { + Some(tcx.hir().impl_item(impl_item.id).expect_type().span) + } else { + None + } + }; // It is fine to skip the binder as we don't care about regions here. match pred.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => { - // The obligation comes not from the current `impl` nor the `trait` being implemented, - // but rather from a "second order" obligation, where an associated type has a - // projection coming from another associated type. See - // `tests/ui/associated-types/point-at-type-on-obligation-failure.rs` and - // `traits-assoc-type-in-supertrait-bad.rs`. - if let Some(ty::Alias(ty::Projection, projection_ty)) = - proj.term.ty().map(|ty| ty.kind()) - && let Some(&impl_item_id) = - tcx.impl_item_implementor_ids(impl_def_id).get(&projection_ty.def_id) - && let Some(impl_item_span) = items - .iter() - .find(|item| item.id.owner_id.to_def_id() == impl_item_id) - .map(fix_span) + // Form 1: The obligation comes not from the current `impl` nor the `trait` being + // implemented, but rather from a "second order" obligation, where an associated + // type has a projection coming from another associated type. + // See `tests/ui/traits/assoc-type-in-superbad.rs` for an example. + if let Some(term_ty) = proj.term.ty() + && let Some(impl_item_span) = ty_to_impl_span(term_ty) { cause.span = impl_item_span; } + + // Form 2: A projection obligation for an associated item failed to be met. + // We overwrite the span from above to ensure that a bound like + // `Self::Assoc1: Trait` gets the same + // span for both obligations that it is lowered to. + if let Some(impl_item_span) = ty_to_impl_span(proj.self_ty()) { + cause.span = impl_item_span; + } } + ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - // An associated item obligation born out of the `trait` failed to be met. An example - // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`. + // Form 3: A trait obligation for an associated item failed to be met. debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred); - if let ty::Alias(ty::Projection, ty::AliasTy { def_id, .. }) = *pred.self_ty().kind() - && let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(&def_id) - && let Some(impl_item_span) = items - .iter() - .find(|item| item.id.owner_id.to_def_id() == impl_item_id) - .map(fix_span) - { + if let Some(impl_item_span) = ty_to_impl_span(pred.self_ty()) { cause.span = impl_item_span; } } @@ -355,9 +382,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { traits::ObligationCauseCode::DerivedObligation, ); } - extend_cause_with_original_assoc_item_obligation( - tcx, trait_ref, item, &mut cause, predicate, - ); + extend_cause_with_original_assoc_item_obligation(tcx, item, &mut cause, predicate); traits::Obligation::with_depth(tcx, cause, depth, param_env, predicate) }; diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 48d9a5e27b7eb..2b6b91672c3a5 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -255,10 +255,9 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option RawVec { } else { // We could use Layout::array here which ensures the absence of isize and usize overflows // and could hypothetically handle differences between stride and size, but this memory - // has already been allocated so we know it can't overflow and currently rust does not + // has already been allocated so we know it can't overflow and currently Rust does not // support such types. So we can do better by skipping some checks and avoid an unwrap. const { assert!(mem::size_of::() % mem::align_of::() == 0) }; unsafe { diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index 8817ec0777b64..31d6bc36fc8b9 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -6,10 +6,10 @@ pub use crate::core_arch::arch::*; /// Inline assembly. /// -/// Refer to [rust by example] for a usage guide and the [reference] for +/// Refer to [Rust By Example] for a usage guide and the [reference] for /// detailed information about the syntax and available options. /// -/// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html #[stable(feature = "asm", since = "1.59.0")] #[rustc_builtin_macro] @@ -19,10 +19,10 @@ pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { /// Module-level inline assembly. /// -/// Refer to [rust by example] for a usage guide and the [reference] for +/// Refer to [Rust By Example] for a usage guide and the [reference] for /// detailed information about the syntax and available options. /// -/// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html #[stable(feature = "global_asm", since = "1.59.0")] #[rustc_builtin_macro] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 643968c35e849..0ee7e190e3d45 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1481,7 +1481,7 @@ pub(crate) mod builtin { /// script](https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script). /// /// When using the `include` macro to include stretches of documentation, remember that the - /// included file still needs to be a valid rust syntax. It is also possible to + /// included file still needs to be a valid Rust syntax. It is also possible to /// use the [`include_str`] macro as `#![doc = include_str!("...")]` (at the module level) or /// `#[doc = include_str!("...")]` (at the item level) to include documentation from a plain /// text or markdown file. diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 3eea065eef64e..3508b0c7f238d 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -3,7 +3,7 @@ use crate::num::NonZero; use crate::{cmp, fmt, hash, mem, num}; /// A type storing a `usize` which is a power of two, and thus -/// represents a possible alignment in the rust abstract machine. +/// represents a possible alignment in the Rust abstract machine. /// /// Note that particularly large alignments, while representable in this type, /// are likely not to be supported by actual allocators and linkers. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index aaedbed0d550c..643b7971a662d 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -23,7 +23,7 @@ use crate::slice; issue = "none", reason = "exposed from core to be reused in std; use the memchr crate" )] -/// Pure rust memchr implementation, taken from rust-memchr +/// Pure Rust memchr implementation, taken from rust-memchr pub mod memchr; #[unstable( diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs index fa02dd52e0027..e8170c13ed263 100644 --- a/library/core/src/sync/exclusive.rs +++ b/library/core/src/sync/exclusive.rs @@ -19,7 +19,7 @@ use core::task::{Context, Poll}; /// /// Certain constructs like [`Future`]s can only be used with _exclusive_ access, /// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the -/// rust compiler that something is `Sync` in practice. +/// Rust compiler that something is `Sync` in practice. /// /// ## Examples /// Using a non-`Sync` future prevents the wrapping struct from being `Sync` diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index e44da8e637e98..8927e9a47fa83 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -157,7 +157,7 @@ impl OsString { /// # Safety /// /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of - /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same rust version + /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version /// built for the same target platform. For example, reconstructing an `OsString` from bytes sent /// over the network or stored in a file will likely violate these safety rules. /// @@ -213,7 +213,7 @@ impl OsString { /// ASCII. /// /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should - /// be treated as opaque and only comparable within the same rust version built for the same + /// be treated as opaque and only comparable within the same Rust version built for the same /// target platform. For example, sending the bytes over the network or storing it in a file /// will likely result in incompatible data. See [`OsString`] for more encoding details /// and [`std::ffi`] for platform-specific, specified conversions. @@ -747,7 +747,7 @@ impl OsStr { /// # Safety /// /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of - /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same rust version + /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version /// built for the same target platform. For example, reconstructing an `OsStr` from bytes sent /// over the network or stored in a file will likely violate these safety rules. /// @@ -955,7 +955,7 @@ impl OsStr { /// ASCII. /// /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should - /// be treated as opaque and only comparable within the same rust version built for the same + /// be treated as opaque and only comparable within the same Rust version built for the same /// target platform. For example, sending the slice over the network or storing it in a file /// will likely result in incompatible byte slices. See [`OsString`] for more encoding details /// and [`std::ffi`] for platform-specific, specified conversions. diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 288cce3aa085e..55a5292a4a41b 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -84,7 +84,7 @@ //! //! # Contributing changes to the documentation //! -//! Check out the rust contribution guidelines [here]( +//! Check out the Rust contribution guidelines [here]( //! https://rustc-dev-guide.rust-lang.org/contributing.html#writing-documentation). //! The source for this documentation can be found on //! [GitHub](https://github.com/rust-lang/rust). diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs index f289dafd8bc56..319b835a76879 100644 --- a/library/std/src/sys/pal/hermit/time.rs +++ b/library/std/src/sys/pal/hermit/time.rs @@ -179,7 +179,7 @@ impl Sub for Instant { /// /// # Panics /// - /// Previous rust versions panicked when `other` was later than `self`. Currently this + /// Previous Rust versions panicked when `other` was later than `self`. Currently this /// method saturates. Future versions may reintroduce the panic in some circumstances. /// See [Monotonicity]. /// diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 91c010ef2b5e4..6f1a354d28a85 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -59,7 +59,7 @@ pub use core::time::TryFromFloatSecsError; /// experience time dilation (slow down or speed up), but it will never go /// backwards. /// As part of this non-guarantee it is also not specified whether system suspends count as -/// elapsed time or not. The behavior varies across platforms and rust versions. +/// elapsed time or not. The behavior varies across platforms and Rust versions. /// /// Instants are opaque types that can only be compared to one another. There is /// no method to get "the number of seconds" from an instant. Instead, it only @@ -142,7 +142,7 @@ pub use core::time::TryFromFloatSecsError; /// where monotonicity is violated, or `Instant`s are subtracted in the wrong order. /// /// This workaround obscures programming errors where earlier and later instants are accidentally -/// swapped. For this reason future rust versions may reintroduce panics. +/// swapped. For this reason future Rust versions may reintroduce panics. /// /// [tier 1]: https://doc.rust-lang.org/rustc/platform-support.html /// [`duration_since`]: Instant::duration_since @@ -290,7 +290,7 @@ impl Instant { /// /// # Panics /// - /// Previous rust versions panicked when `earlier` was later than `self`. Currently this + /// Previous Rust versions panicked when `earlier` was later than `self`. Currently this /// method saturates. Future versions may reintroduce the panic in some circumstances. /// See [Monotonicity]. /// @@ -365,7 +365,7 @@ impl Instant { /// /// # Panics /// - /// Previous rust versions panicked when the current time was earlier than self. Currently this + /// Previous Rust versions panicked when the current time was earlier than self. Currently this /// method returns a Duration of zero in that case. Future versions may reintroduce the panic. /// See [Monotonicity]. /// @@ -450,7 +450,7 @@ impl Sub for Instant { /// /// # Panics /// - /// Previous rust versions panicked when `other` was later than `self`. Currently this + /// Previous Rust versions panicked when `other` was later than `self`. Currently this /// method saturates. Future versions may reintroduce the panic in some circumstances. /// See [Monotonicity]. /// diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs index 22c28e4954eff..875c66e5fa32c 100644 --- a/library/test/src/formatters/terse.rs +++ b/library/test/src/formatters/terse.rs @@ -84,7 +84,7 @@ impl TerseFormatter { if self.test_column % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 { // We insert a new line regularly in order to flush the // screen when dealing with line-buffered output (e.g., piping to - // `stamp` in the rust CI). + // `stamp` in the Rust CI). self.write_progress()?; } diff --git a/library/test/src/types.rs b/library/test/src/types.rs index 1a8ae889c8c1b..6a7035a8e2918 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -13,7 +13,7 @@ pub use NamePadding::*; pub use TestFn::*; pub use TestName::*; -/// Type of the test according to the [rust book](https://doc.rust-lang.org/cargo/guide/tests.html) +/// Type of the test according to the [Rust book](https://doc.rust-lang.org/cargo/guide/tests.html) /// conventions. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum TestType { diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 6c7cc3bf6a736..c8c32fb8699f5 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -129,6 +129,7 @@ pub struct RustcDocs { impl Step for RustcDocs { type Output = Option; const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index a4903ce235365..c4235755ba865 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -797,7 +797,10 @@ impl Step for Rustc { cargo.rustdocflag("-Zunstable-options"); cargo.rustdocflag("-Znormalize-docs"); cargo.rustdocflag("--show-type-layout"); - cargo.rustdocflag("--generate-link-to-definition"); + // FIXME: `--generate-link-to-definition` tries to resolve cfged out code + // see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222 + // cargo.rustdocflag("--generate-link-to-definition"); + compile::rustc_cargo(builder, &mut cargo, target, compiler.stage); cargo.arg("-Zunstable-options"); cargo.arg("-Zskip-rustdoc-fingerprint"); @@ -953,8 +956,10 @@ macro_rules! tool_doc { cargo.rustdocflag("-Arustdoc::private-intra-doc-links"); cargo.rustdocflag("--enable-index-page"); cargo.rustdocflag("--show-type-layout"); - cargo.rustdocflag("--generate-link-to-definition"); cargo.rustdocflag("-Zunstable-options"); + // FIXME: `--generate-link-to-definition` tries to resolve cfged out code + // see https://github.com/rust-lang/rust/pull/122066#issuecomment-1983049222 + // cargo.rustdocflag("--generate-link-to-definition"); let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"); $(for krate in $crates { diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs index 9f46772456518..db0768848fd37 100644 --- a/src/tools/miri/tests/compiletest.rs +++ b/src/tools/miri/tests/compiletest.rs @@ -81,8 +81,10 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> // Add a test env var to do environment communication tests. program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into()))); + // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find). - program.envs.push(("MIRI_TEMP".into(), Some(env::temp_dir().into()))); + let miri_temp = env::var_os("MIRI_TEMP").unwrap_or_else(|| env::temp_dir().into()); + program.envs.push(("MIRI_TEMP".into(), Some(miri_temp))); let mut config = Config { target: Some(target.to_owned()), diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 6ba39c1f563f9..304a178dc3404 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -1,6 +1,10 @@ //@ignore-target-windows: File handling is not implemented yet //@compile-flags: -Zmiri-disable-isolation +// If this test is failing for you locally, you can try +// 1. Deleting the files `/tmp/miri_*` +// 2. Setting `MIRI_TEMP` or `TMPDIR` to a different directory, without the `miri_*` files + #![feature(io_error_more)] #![feature(io_error_uncategorized)] diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index a9c5be913ba1e..1a53637ad42f9 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -190,7 +190,11 @@ pub fn check(path: &Path, bless: bool, bad: &mut bool) { let blessed_issues_path = tidy_src.join("issues_blessed.txt"); let mut blessed_issues_txt = fs::File::create(&blessed_issues_path).unwrap(); blessed_issues_txt.write(issues_txt_header.as_bytes()).unwrap(); - for filename in allowed_issue_names.difference(&remaining_issue_names) { + // If we changed paths to use the OS separator, reassert Unix chauvinism for blessing. + for filename in allowed_issue_names + .difference(&remaining_issue_names) + .map(|s| s.replace(std::path::MAIN_SEPARATOR_STR, "/")) + { write!(blessed_issues_txt, "\"{filename}\",\n").unwrap(); } write!(blessed_issues_txt, "]\n").unwrap(); diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr index 2a308f83731fa..03d72f2ae2c6e 100644 --- a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr +++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr @@ -1,11 +1,8 @@ -error[E0191]: the value of the associated types `Item`, `Item`, `IntoIter` and `IntoIter` in `IntoIterator` must be specified +error[E0191]: the value of the associated types `Item` and `IntoIter` in `IntoIterator` must be specified --> $DIR/overlaping-bound-suggestion.rs:7:13 | LL | inner: >::IntoIterator as Item>::Core, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | | - | | associated types `Item`, `IntoIter` must be specified - | associated types `Item`, `IntoIter` must be specified + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: specify the associated types: `IntoIterator, Item = Type, IntoIter = Type>` error[E0223]: ambiguous associated type --> $DIR/overlaping-bound-suggestion.rs:7:13 diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.rs b/tests/ui/associated-types/hr-associated-type-projection-1.rs index 3df3f68ab1eed..d7fc5d122c3ec 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.rs +++ b/tests/ui/associated-types/hr-associated-type-projection-1.rs @@ -11,8 +11,8 @@ where } impl UnsafeCopy<'_, T> for T { - //~^ type mismatch resolving `::Target == T` type Item = T; + //~^ type mismatch resolving `::Target == T` } pub fn main() { diff --git a/tests/ui/associated-types/hr-associated-type-projection-1.stderr b/tests/ui/associated-types/hr-associated-type-projection-1.stderr index 65221718ee661..b871bb51ae313 100644 --- a/tests/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/tests/ui/associated-types/hr-associated-type-projection-1.stderr @@ -1,10 +1,10 @@ error[E0271]: type mismatch resolving `::Target == T` - --> $DIR/hr-associated-type-projection-1.rs:13:33 + --> $DIR/hr-associated-type-projection-1.rs:14:17 | LL | impl UnsafeCopy<'_, T> for T { - | - ^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type - | | - | expected this type parameter + | - expected this type parameter +LL | type Item = T; + | ^ expected type parameter `T`, found associated type | = note: expected type parameter `T` found associated type `::Target` diff --git a/tests/ui/crate-loading/missing-std.stderr b/tests/ui/crate-loading/missing-std.stderr index 70bcae1e0edd0..3eb6c2946d354 100644 --- a/tests/ui/crate-loading/missing-std.stderr +++ b/tests/ui/crate-loading/missing-std.stderr @@ -8,8 +8,6 @@ LL | extern crate core; = help: consider downloading the target with `rustup target add x86_64-unknown-uefi` = help: consider building the standard library from source with `cargo build -Zbuild-std` -error: requires `sized` lang_item - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/issues/issue-33941.rs b/tests/ui/issues/issue-33941.rs index 0ad7cbe8efc41..7b5be30834b9d 100644 --- a/tests/ui/issues/issue-33941.rs +++ b/tests/ui/issues/issue-33941.rs @@ -5,5 +5,4 @@ use std::collections::HashMap; fn main() { for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` //~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - //~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` } diff --git a/tests/ui/issues/issue-33941.stderr b/tests/ui/issues/issue-33941.stderr index e7f4a4fa004ce..f1b6b6ba17edc 100644 --- a/tests/ui/issues/issue-33941.stderr +++ b/tests/ui/issues/issue-33941.stderr @@ -27,16 +27,6 @@ LL | for _ in HashMap::new().iter().cloned() {} = note: required for `Cloned>` to implement `Iterator` = note: required for `Cloned>` to implement `IntoIterator` -error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)` - --> $DIR/issue-33941.rs:6:14 - | -LL | for _ in HashMap::new().iter().cloned() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `(&_, &_)`, found `&_` - | - = note: expected tuple `(&_, &_)` - found reference `&_` - = note: required for `Cloned>` to implement `Iterator` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/issues/issue-37131.stderr b/tests/ui/issues/issue-37131.stderr index 9ecae3e7a2b24..588696f354184 100644 --- a/tests/ui/issues/issue-37131.stderr +++ b/tests/ui/issues/issue-37131.stderr @@ -4,8 +4,6 @@ error[E0463]: can't find crate for `std` = help: consider downloading the target with `rustup target add thumbv6m-none-eabi` = help: consider building the standard library from source with `cargo build -Zbuild-std` -error: requires `sized` lang_item - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/issues/issue-49851/compiler-builtins-error.rs b/tests/ui/issues/issue-49851/compiler-builtins-error.rs index 3b62cc73f93d6..db45d040f7914 100644 --- a/tests/ui/issues/issue-49851/compiler-builtins-error.rs +++ b/tests/ui/issues/issue-49851/compiler-builtins-error.rs @@ -1,5 +1,4 @@ //~ ERROR can't find crate for `core` -//~^ ERROR can't find crate for `compiler_builtins` //@ compile-flags: --target thumbv7em-none-eabihf //@ needs-llvm-components: arm @@ -8,6 +7,5 @@ #![no_std] extern crate cortex_m; -//~^ ERROR can't find crate for `cortex_m` fn main() {} diff --git a/tests/ui/issues/issue-49851/compiler-builtins-error.stderr b/tests/ui/issues/issue-49851/compiler-builtins-error.stderr index fcfa2bf119cff..1cd65a1b68c88 100644 --- a/tests/ui/issues/issue-49851/compiler-builtins-error.stderr +++ b/tests/ui/issues/issue-49851/compiler-builtins-error.stderr @@ -4,16 +4,6 @@ error[E0463]: can't find crate for `core` = help: consider downloading the target with `rustup target add thumbv7em-none-eabihf` = help: consider building the standard library from source with `cargo build -Zbuild-std` -error[E0463]: can't find crate for `compiler_builtins` - -error[E0463]: can't find crate for `cortex_m` - --> $DIR/compiler-builtins-error.rs:10:1 - | -LL | extern crate cortex_m; - | ^^^^^^^^^^^^^^^^^^^^^^ can't find crate - -error: requires `sized` lang_item - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs index ed4de58cd23ce..521eb6a818b0c 100644 --- a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs +++ b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs @@ -1,3 +1,10 @@ +#![allow(unused)] + +fn test_122112() { + // Make sure we don't ICE if parsing in recovery fails + let _: std::env::temp_dir().join(&self, push: Box); //~ ERROR expected one of +} + fn main() { let _: std::env::temp_dir().join("foo"); //~ ERROR expected one of } diff --git a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr index d03f3ae02830b..15c27bb9451b6 100644 --- a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr +++ b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr @@ -1,5 +1,13 @@ error: expected one of `!`, `+`, `->`, `::`, `;`, or `=`, found `.` - --> $DIR/recover-colon-instead-of-eq-in-local.rs:2:32 + --> $DIR/recover-colon-instead-of-eq-in-local.rs:5:32 + | +LL | let _: std::env::temp_dir().join(&self, push: Box); + | - ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=` + | | + | while parsing the type for `_` + +error: expected one of `!`, `+`, `->`, `::`, `;`, or `=`, found `.` + --> $DIR/recover-colon-instead-of-eq-in-local.rs:9:32 | LL | let _: std::env::temp_dir().join("foo"); | - ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=` @@ -7,5 +15,5 @@ LL | let _: std::env::temp_dir().join("foo"); | while parsing the type for `_` | help: use `=` if you meant to assign -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.rs b/tests/ui/trait-bounds/super-assoc-mismatch.rs new file mode 100644 index 0000000000000..97dfec80e3167 --- /dev/null +++ b/tests/ui/trait-bounds/super-assoc-mismatch.rs @@ -0,0 +1,60 @@ +trait Super { + type Assoc; +} +impl Super for () { + type Assoc = u8; +} +trait Sub: Super {} + +trait BoundOnSelf: Sub {} +impl BoundOnSelf for () {} +//~^ ERROR the trait bound `(): Sub` is not satisfied + +trait BoundOnParam {} +impl BoundOnParam<()> for () {} +//~^ ERROR the trait bound `(): Sub` is not satisfied + +trait BoundOnAssoc { + type Assoc: Sub; +} +impl BoundOnAssoc for () { + type Assoc = (); + //~^ ERROR the trait bound `(): Sub` is not satisfied +} + +trait BoundOnGat where Self::Assoc: Sub { + type Assoc; +} +impl BoundOnGat for u8 { + type Assoc = (); + //~^ ERROR the trait bound `(): Sub` is not satisfied +} + +fn trivial_bound() where (): Sub {} +//~^ ERROR the trait bound `(): Sub` is not satisfied + +// The following is an edge case where the unsatisfied projection predicate +// `<::Assoc1<()> as SuperGeneric>::Assoc == ::Assoc2` +// contains both associated types of `MultiAssoc`. To suppress the error about the unsatisfied +// super projection, the error's span must be equal to the span of the unsatisfied trait error. +trait SuperGeneric { + type Assoc; +} +trait SubGeneric: SuperGeneric {} +trait MultiAssoc +where + Self::Assoc1<()>: SubGeneric +{ + type Assoc1; + type Assoc2; +} +impl SuperGeneric for () { + type Assoc = u8; +} +impl MultiAssoc for u8 { + type Assoc1 = (); + //~^ ERROR the trait bound `(): SubGeneric` is not satisfied + type Assoc2 = u16; +} + +fn main() {} diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.stderr b/tests/ui/trait-bounds/super-assoc-mismatch.stderr new file mode 100644 index 0000000000000..47535776348b9 --- /dev/null +++ b/tests/ui/trait-bounds/super-assoc-mismatch.stderr @@ -0,0 +1,105 @@ +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:10:22 + | +LL | impl BoundOnSelf for () {} + | ^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnSelf` + --> $DIR/super-assoc-mismatch.rs:9:20 + | +LL | trait BoundOnSelf: Sub {} + | ^^^ required by this bound in `BoundOnSelf` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:14:27 + | +LL | impl BoundOnParam<()> for () {} + | ^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnParam` + --> $DIR/super-assoc-mismatch.rs:13:23 + | +LL | trait BoundOnParam {} + | ^^^ required by this bound in `BoundOnParam` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:21:18 + | +LL | type Assoc = (); + | ^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnAssoc::Assoc` + --> $DIR/super-assoc-mismatch.rs:18:17 + | +LL | type Assoc: Sub; + | ^^^ required by this bound in `BoundOnAssoc::Assoc` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:29:21 + | +LL | type Assoc = (); + | ^^ the trait `Sub` is not implemented for `()`, which is required by `::Assoc: Sub` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `BoundOnGat` + --> $DIR/super-assoc-mismatch.rs:25:41 + | +LL | trait BoundOnGat where Self::Assoc: Sub { + | ^^^ required by this bound in `BoundOnGat` + +error[E0277]: the trait bound `(): Sub` is not satisfied + --> $DIR/super-assoc-mismatch.rs:33:26 + | +LL | fn trivial_bound() where (): Sub {} + | ^^^^^^^ the trait `Sub` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:7:1 + | +LL | trait Sub: Super {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable + +error[E0277]: the trait bound `(): SubGeneric` is not satisfied + --> $DIR/super-assoc-mismatch.rs:55:22 + | +LL | type Assoc1 = (); + | ^^ the trait `SubGeneric` is not implemented for `()`, which is required by `::Assoc1<()>: SubGeneric<::Assoc2>` + | +help: this trait has no implementations, consider adding one + --> $DIR/super-assoc-mismatch.rs:43:1 + | +LL | trait SubGeneric: SuperGeneric {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `MultiAssoc` + --> $DIR/super-assoc-mismatch.rs:46:23 + | +LL | trait MultiAssoc + | ---------- required by a bound in this trait +LL | where +LL | Self::Assoc1<()>: SubGeneric + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `MultiAssoc` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/alias/only-require-assocs-from-supertraits.rs b/tests/ui/traits/alias/only-require-assocs-from-supertraits.rs new file mode 100644 index 0000000000000..35149fdfba084 --- /dev/null +++ b/tests/ui/traits/alias/only-require-assocs-from-supertraits.rs @@ -0,0 +1,16 @@ +//@ check-pass + +#![feature(trait_alias)] + +trait Foo {} +trait Bar { type Assoc; } + +trait Alias = Foo; + +// Check that an alias only requires us to specify the associated types +// of the principal's supertraits. For example, we shouldn't require +// specifying the type `Assoc` on trait `Bar` just because we have some +// `T: Bar` where clause on the alias... because that makes no sense. +fn use_alias(x: &dyn Alias) {} + +fn main() {}