diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
39 files changed, 1186 insertions, 1348 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index 3e700f2da..0748644cc 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -3,8 +3,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_lint_defs::Applicability; -use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt}; +use rustc_middle::ty::{self as ty, Ty}; use rustc_span::symbol::Ident; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; @@ -135,17 +134,6 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { only_self_bounds, ); } - &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { - self.instantiate_lang_item_trait_ref( - lang_item, - span, - hir_id, - args, - param_ty, - bounds, - only_self_bounds, - ); - } hir::GenericBound::Outlives(lifetime) => { let region = self.ast_region_to_region(lifetime, None); bounds.push_region_bound( @@ -194,8 +182,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { self.add_bounds( param_ty, - ast_bounds.iter().filter(|bound| { - match filter { + ast_bounds.iter().filter(|bound| match filter { PredicateFilter::All | PredicateFilter::SelfOnly | PredicateFilter::SelfAndAssociatedTypeBounds => true, @@ -209,7 +196,6 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { false } } - } }), &mut bounds, ty::List::empty(), @@ -258,64 +244,49 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let tcx = self.tcx(); - let return_type_notation = - binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation; - - let candidate = if return_type_notation { - if self.trait_defines_associated_item_named( - trait_ref.def_id(), - ty::AssocKind::Fn, - binding.item_name, - ) { - trait_ref + let assoc_kind = + if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation { + ty::AssocKind::Fn + } else if let ConvertedBindingKind::Equality(term) = binding.kind + && let ty::TermKind::Const(_) = term.node.unpack() + { + ty::AssocKind::Const } else { - self.one_bound_for_assoc_method( - traits::supertraits(tcx, trait_ref), - trait_ref.print_only_trait_path(), - binding.item_name, - path_span, - )? - } - } else if self.trait_defines_associated_item_named( + ty::AssocKind::Type + }; + + let candidate = if self.trait_defines_associated_item_named( trait_ref.def_id(), - ty::AssocKind::Type, + assoc_kind, binding.item_name, ) { - // Simple case: X is defined in the current trait. + // Simple case: The assoc item is defined in the current trait. trait_ref } else { // Otherwise, we have to walk through the supertraits to find - // those that do. - self.one_bound_for_assoc_type( + // one that does define it. + self.one_bound_for_assoc_item( || traits::supertraits(tcx, trait_ref), trait_ref.skip_binder().print_only_trait_name(), None, + assoc_kind, binding.item_name, path_span, - match binding.kind { - ConvertedBindingKind::Equality(term) => Some(term), - _ => None, - }, + Some(&binding), )? }; let (assoc_ident, def_scope) = tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id); - // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead - // of calling `filter_by_name_and_kind`. - let find_item_of_kind = |kind| { - tcx.associated_items(candidate.def_id()) - .filter_by_name_unhygienic(assoc_ident.name) - .find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident) - }; - let assoc_item = if return_type_notation { - find_item_of_kind(ty::AssocKind::Fn) - } else { - find_item_of_kind(ty::AssocKind::Type) - .or_else(|| find_item_of_kind(ty::AssocKind::Const)) - } - .expect("missing associated type"); + // We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()` + // instead of calling `filter_by_name_and_kind` which would needlessly normalize the + // `assoc_ident` again and again. + let assoc_item = tcx + .associated_items(candidate.def_id()) + .filter_by_name_unhygienic(assoc_ident.name) + .find(|i| i.kind == assoc_kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident) + .expect("missing associated item"); if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) { tcx.sess @@ -342,7 +313,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { .or_insert(binding.span); } - let projection_ty = if return_type_notation { + let projection_ty = if let ty::AssocKind::Fn = assoc_kind { let mut emitted_bad_param_err = false; // If we have an method return type bound, then we need to substitute // the method's early bound params with suitable late-bound params. @@ -350,7 +321,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let args = candidate.skip_binder().args.extend_to(tcx, assoc_item.def_id, |param, _| { let subst = match param.kind { - ty::GenericParamDefKind::Lifetime => ty::Region::new_late_bound( + ty::GenericParamDefKind::Lifetime => ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { @@ -469,7 +440,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let late_bound_in_trait_ref = tcx.collect_constrained_late_bound_regions(&projection_ty); let late_bound_in_ty = - tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty)); + tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty.node)); debug!(?late_bound_in_trait_ref); debug!(?late_bound_in_ty); @@ -494,77 +465,27 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { } } - let assoc_item_def_id = projection_ty.skip_binder().def_id; - let def_kind = tcx.def_kind(assoc_item_def_id); match binding.kind { - ConvertedBindingKind::Equality(..) if return_type_notation => { + ConvertedBindingKind::Equality(..) if let ty::AssocKind::Fn = assoc_kind => { return Err(self.tcx().sess.emit_err( crate::errors::ReturnTypeNotationEqualityBound { span: binding.span }, )); } - ConvertedBindingKind::Equality(mut term) => { + ConvertedBindingKind::Equality(term) => { // "Desugar" a constraint like `T: Iterator<Item = u32>` this to // the "projection predicate" for: // // `<T as Iterator>::Item = u32` - match (def_kind, term.unpack()) { - (DefKind::AssocTy, ty::TermKind::Ty(_)) - | (DefKind::AssocConst, ty::TermKind::Const(_)) => (), - (_, _) => { - let got = if let Some(_) = term.ty() { "type" } else { "constant" }; - let expected = tcx.def_descr(assoc_item_def_id); - let mut err = tcx.sess.struct_span_err( - binding.span, - format!("expected {expected} bound, found {got}"), - ); - err.span_note( - tcx.def_span(assoc_item_def_id), - format!("{expected} defined here"), - ); - - if let DefKind::AssocConst = def_kind - && let Some(t) = term.ty() - && (t.is_enum() || t.references_error()) - && tcx.features().associated_const_equality - { - err.span_suggestion( - binding.span, - "if equating a const, try wrapping with braces", - format!("{} = {{ const }}", binding.item_name), - Applicability::HasPlaceholders, - ); - } - let reported = err.emit(); - term = match def_kind { - DefKind::AssocTy => Ty::new_error(tcx, reported).into(), - DefKind::AssocConst => ty::Const::new_error( - tcx, - reported, - tcx.type_of(assoc_item_def_id) - .instantiate(tcx, projection_ty.skip_binder().args), - ) - .into(), - _ => unreachable!(), - }; - } - } bounds.push_projection_bound( tcx, - projection_ty - .map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }), + projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate { + projection_ty, + term: term.node, + }), binding.span, ); } ConvertedBindingKind::Constraint(ast_bounds) => { - match def_kind { - DefKind::AssocTy => {} - _ => { - return Err(tcx.sess.emit_err(errors::AssocBoundOnConst { - span: assoc_ident.span, - descr: tcx.def_descr(assoc_item_def_id), - })); - } - } // "Desugar" a constraint like `T: Iterator<Item: Debug>` to // // `<T as Iterator>::Item: Debug` diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 32be7e083..13ad9a453 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -1,23 +1,22 @@ -use crate::astconv::AstConv; +use crate::astconv::{AstConv, ConvertedBindingKind}; use crate::errors::{ - AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams, + self, AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams, ParenthesizedFnTraitExpansion, }; +use crate::fluent_generated as fluent; use crate::traits::error_reporting::report_object_safety_error; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::traits::FulfillmentError; -use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TyCtxt}; +use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TyCtxt, TypeVisitableExt}; use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, Symbol, DUMMY_SP}; use rustc_trait_selection::traits::object_safety_violations_for_assoc_item; -use std::collections::BTreeSet; - impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// On missing type parameters, emit an E0393 error and provide a structured suggestion using /// the type parameter's name as a placeholder. @@ -99,83 +98,88 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - pub(crate) fn complain_about_assoc_type_not_found<I>( + pub(super) fn complain_about_assoc_item_not_found<I>( &self, all_candidates: impl Fn() -> I, ty_param_name: &str, ty_param_def_id: Option<LocalDefId>, + assoc_kind: ty::AssocKind, assoc_name: Ident, span: Span, + binding: Option<&super::ConvertedBinding<'_, 'tcx>>, ) -> ErrorGuaranteed where I: Iterator<Item = ty::PolyTraitRef<'tcx>>, { + let tcx = self.tcx(); + + // First and foremost, provide a more user-friendly & “intuitive” error on kind mismatches. + if let Some(assoc_item) = all_candidates().find_map(|r| { + tcx.associated_items(r.def_id()) + .filter_by_name_unhygienic(assoc_name.name) + .find(|item| tcx.hygienic_eq(assoc_name, item.ident(tcx), r.def_id())) + }) { + return self.complain_about_assoc_kind_mismatch( + assoc_item, assoc_kind, assoc_name, span, binding, + ); + } + + let assoc_kind_str = super::assoc_kind_str(assoc_kind); + // The fallback span is needed because `assoc_name` might be an `Fn()`'s `Output` without a // valid span, so we point at the whole path segment instead. let is_dummy = assoc_name.span == DUMMY_SP; - let mut err = struct_span_err!( - self.tcx().sess, - if is_dummy { span } else { assoc_name.span }, - E0220, - "associated type `{}` not found for `{}`", + let mut err = errors::AssocItemNotFound { + span: if is_dummy { span } else { assoc_name.span }, assoc_name, - ty_param_name - ); + assoc_kind: assoc_kind_str, + ty_param_name, + label: None, + sugg: None, + }; if is_dummy { - err.span_label(span, format!("associated type `{assoc_name}` not found")); - return err.emit(); + err.label = Some(errors::AssocItemNotFoundLabel::NotFound { span }); + return tcx.sess.emit_err(err); } let all_candidate_names: Vec<_> = all_candidates() - .flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order()) + .flat_map(|r| tcx.associated_items(r.def_id()).in_definition_order()) .filter_map(|item| { - if !item.is_impl_trait_in_trait() && item.kind == ty::AssocKind::Type { - Some(item.name) - } else { - None - } + (!item.is_impl_trait_in_trait() && item.kind == assoc_kind).then_some(item.name) }) .collect(); if let Some(suggested_name) = find_best_match_for_name(&all_candidate_names, assoc_name.name, None) { - err.span_suggestion( - assoc_name.span, - "there is an associated type with a similar name", + err.sugg = Some(errors::AssocItemNotFoundSugg::Similar { + span: assoc_name.span, + assoc_kind: assoc_kind_str, suggested_name, - Applicability::MaybeIncorrect, - ); - return err.emit(); + }); + return tcx.sess.emit_err(err); } // If we didn't find a good item in the supertraits (or couldn't get // the supertraits), like in ItemCtxt, then look more generally from // all visible traits. If there's one clear winner, just suggest that. - let visible_traits: Vec<_> = self - .tcx() + let visible_traits: Vec<_> = tcx .all_traits() .filter(|trait_def_id| { - let viz = self.tcx().visibility(*trait_def_id); + let viz = tcx.visibility(*trait_def_id); let def_id = self.item_def_id(); - viz.is_accessible_from(def_id, self.tcx()) + viz.is_accessible_from(def_id, tcx) }) .collect(); let wider_candidate_names: Vec<_> = visible_traits .iter() - .flat_map(|trait_def_id| { - self.tcx().associated_items(*trait_def_id).in_definition_order() - }) + .flat_map(|trait_def_id| tcx.associated_items(*trait_def_id).in_definition_order()) .filter_map(|item| { - if !item.is_impl_trait_in_trait() && item.kind == ty::AssocKind::Type { - Some(item.name) - } else { - None - } + (!item.is_impl_trait_in_trait() && item.kind == assoc_kind).then_some(item.name) }) .collect(); @@ -184,96 +188,155 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { if let [best_trait] = visible_traits .iter() + .copied() .filter(|trait_def_id| { - self.tcx() - .associated_items(*trait_def_id) + tcx.associated_items(trait_def_id) .filter_by_name_unhygienic(suggested_name) - .any(|item| item.kind == ty::AssocKind::Type) + .any(|item| item.kind == assoc_kind) }) .collect::<Vec<_>>()[..] { - let trait_name = self.tcx().def_path_str(*best_trait); - let an = if suggested_name != assoc_name.name { "a similarly named" } else { "an" }; - err.span_label( - assoc_name.span, - format!( - "there is {an} associated type `{suggested_name}` in the \ - trait `{trait_name}`", - ), - ); - let hir = self.tcx().hir(); + let trait_name = tcx.def_path_str(best_trait); + err.label = Some(errors::AssocItemNotFoundLabel::FoundInOtherTrait { + span: assoc_name.span, + assoc_kind: assoc_kind_str, + trait_name: &trait_name, + suggested_name, + identically_named: suggested_name == assoc_name.name, + }); + let hir = tcx.hir(); if let Some(def_id) = ty_param_def_id - && let parent = hir.get_parent_item(hir.local_def_id_to_hir_id(def_id)) + && let parent = hir.get_parent_item(tcx.local_def_id_to_hir_id(def_id)) && let Some(generics) = hir.get_generics(parent.def_id) { - if generics.bounds_for_param(def_id) - .flat_map(|pred| pred.bounds.iter()) - .any(|b| match b { + if generics.bounds_for_param(def_id).flat_map(|pred| pred.bounds.iter()).any( + |b| match b { hir::GenericBound::Trait(t, ..) => { - t.trait_ref.trait_def_id().as_ref() == Some(best_trait) + t.trait_ref.trait_def_id() == Some(best_trait) } _ => false, - }) - { + }, + ) { // The type param already has a bound for `trait_name`, we just need to - // change the associated type. - err.span_suggestion_verbose( - assoc_name.span, - format!( - "change the associated type name to use `{suggested_name}` from \ - `{trait_name}`", - ), - suggested_name.to_string(), - Applicability::MaybeIncorrect, - ); - } else if suggest_constraining_type_param( - self.tcx(), - generics, - &mut err, - &ty_param_name, - &trait_name, - None, - None, - ) - && suggested_name != assoc_name.name + // change the associated item. + err.sugg = Some(errors::AssocItemNotFoundSugg::SimilarInOtherTrait { + span: assoc_name.span, + assoc_kind: assoc_kind_str, + suggested_name, + }); + return tcx.sess.emit_err(err); + } + + let mut err = tcx.sess.create_err(err); + if suggest_constraining_type_param( + tcx, + generics, + &mut err, + &ty_param_name, + &trait_name, + None, + None, + ) && suggested_name != assoc_name.name { // We suggested constraining a type parameter, but the associated type on it // was also not an exact match, so we also suggest changing it. err.span_suggestion_verbose( assoc_name.span, - "and also change the associated type name", + fluent::hir_analysis_assoc_item_not_found_similar_in_other_trait_with_bound_sugg, suggested_name.to_string(), Applicability::MaybeIncorrect, ); } + return err.emit(); } - return err.emit(); + return tcx.sess.emit_err(err); } } // If we still couldn't find any associated type, and only one associated type exists, // suggests using it. - - if all_candidate_names.len() == 1 { + if let [candidate_name] = all_candidate_names.as_slice() { // this should still compile, except on `#![feature(associated_type_defaults)]` // where it could suggests `type A = Self::A`, thus recursing infinitely - let applicability = if self.tcx().features().associated_type_defaults { + let applicability = if tcx.features().associated_type_defaults { Applicability::Unspecified } else { Applicability::MaybeIncorrect }; - err.span_suggestion( - assoc_name.span, - format!("`{ty_param_name}` has the following associated type"), - all_candidate_names.first().unwrap().to_string(), + err.sugg = Some(errors::AssocItemNotFoundSugg::Other { + span: assoc_name.span, applicability, - ); + ty_param_name, + assoc_kind: assoc_kind_str, + suggested_name: *candidate_name, + }); } else { - err.span_label(assoc_name.span, format!("associated type `{assoc_name}` not found")); + err.label = Some(errors::AssocItemNotFoundLabel::NotFound { span: assoc_name.span }); } - err.emit() + tcx.sess.emit_err(err) + } + + fn complain_about_assoc_kind_mismatch( + &self, + assoc_item: &ty::AssocItem, + assoc_kind: ty::AssocKind, + ident: Ident, + span: Span, + binding: Option<&super::ConvertedBinding<'_, 'tcx>>, + ) -> ErrorGuaranteed { + let tcx = self.tcx(); + + let bound_on_assoc_const_label = if let ty::AssocKind::Const = assoc_item.kind + && let Some(binding) = binding + && let ConvertedBindingKind::Constraint(_) = binding.kind + { + let lo = if binding.gen_args.span_ext.is_dummy() { + ident.span + } else { + binding.gen_args.span_ext + }; + Some(lo.between(span.shrink_to_hi())) + } else { + None + }; + + // FIXME(associated_const_equality): This has quite a few false positives and negatives. + let wrap_in_braces_sugg = if let Some(binding) = binding + && let ConvertedBindingKind::Equality(term) = binding.kind + && let ty::TermKind::Ty(ty) = term.node.unpack() + && (ty.is_enum() || ty.references_error()) + && tcx.features().associated_const_equality + { + Some(errors::AssocKindMismatchWrapInBracesSugg { + lo: term.span.shrink_to_lo(), + hi: term.span.shrink_to_hi(), + }) + } else { + None + }; + + // For equality bounds, we want to blame the term (RHS) instead of the item (LHS) since + // one can argue that that's more “untuitive” to the user. + let (span, expected_because_label, expected, got) = if let Some(binding) = binding + && let ConvertedBindingKind::Equality(term) = binding.kind + { + (term.span, Some(ident.span), assoc_item.kind, assoc_kind) + } else { + (ident.span, None, assoc_kind, assoc_item.kind) + }; + + tcx.sess.emit_err(errors::AssocKindMismatch { + span, + expected: super::assoc_kind_str(expected), + got: super::assoc_kind_str(got), + expected_because_label, + assoc_kind: super::assoc_kind_str(assoc_item.kind), + def_span: tcx.def_span(assoc_item.def_id), + bound_on_assoc_const_label, + wrap_in_braces_sugg, + }) } pub(crate) fn complain_about_ambiguous_inherent_assoc_type( @@ -506,23 +569,24 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// emit a generic note suggesting using a `where` clause to constraint instead. pub(crate) fn complain_about_missing_associated_types( &self, - associated_types: FxHashMap<Span, BTreeSet<DefId>>, + associated_types: FxIndexMap<Span, FxIndexSet<DefId>>, potential_assoc_types: Vec<Span>, trait_bounds: &[hir::PolyTraitRef<'_>], ) { if associated_types.values().all(|v| v.is_empty()) { return; } + let tcx = self.tcx(); // FIXME: Marked `mut` so that we can replace the spans further below with a more // appropriate one, but this should be handled earlier in the span assignment. - let mut associated_types: FxHashMap<Span, Vec<_>> = associated_types + let mut associated_types: FxIndexMap<Span, Vec<_>> = associated_types .into_iter() .map(|(span, def_ids)| { (span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect()) }) .collect(); - let mut names: FxHashMap<String, Vec<Symbol>> = Default::default(); + let mut names: FxIndexMap<String, Vec<Symbol>> = Default::default(); let mut names_len = 0; // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and @@ -585,6 +649,32 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } + // We get all the associated items that _are_ set, + // so that we can check if any of their names match one of the ones we are missing. + // This would mean that they are shadowing the associated type we are missing, + // and we can then use their span to indicate this to the user. + let bound_names = trait_bounds + .iter() + .filter_map(|poly_trait_ref| { + let path = poly_trait_ref.trait_ref.path.segments.last()?; + let args = path.args?; + + Some(args.bindings.iter().filter_map(|binding| { + let ident = binding.ident; + let trait_def = path.res.def_id(); + let assoc_item = tcx.associated_items(trait_def).find_by_name_and_kind( + tcx, + ident, + ty::AssocKind::Type, + trait_def, + ); + + Some((ident.name, assoc_item?)) + })) + }) + .flatten() + .collect::<FxHashMap<Symbol, &ty::AssocItem>>(); + let mut names = names .into_iter() .map(|(trait_, mut assocs)| { @@ -625,16 +715,42 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { *names.entry(item.name).or_insert(0) += 1; } let mut dupes = false; + let mut shadows = false; for item in assoc_items { let prefix = if names[&item.name] > 1 { let trait_def_id = item.container_id(tcx); dupes = true; format!("{}::", tcx.def_path_str(trait_def_id)) + } else if bound_names.get(&item.name).is_some_and(|x| x != &item) { + let trait_def_id = item.container_id(tcx); + shadows = true; + format!("{}::", tcx.def_path_str(trait_def_id)) } else { String::new() }; + + let mut is_shadowed = false; + + if let Some(assoc_item) = bound_names.get(&item.name) + && assoc_item != &item + { + is_shadowed = true; + + let rename_message = + if assoc_item.def_id.is_local() { ", consider renaming it" } else { "" }; + err.span_label( + tcx.def_span(assoc_item.def_id), + format!("`{}{}` shadowed here{}", prefix, item.name, rename_message), + ); + } + + let rename_message = if is_shadowed { ", consider renaming it" } else { "" }; + if let Some(sp) = tcx.hir().span_if_local(item.def_id) { - err.span_label(sp, format!("`{}{}` defined here", prefix, item.name)); + err.span_label( + sp, + format!("`{}{}` defined here{}", prefix, item.name, rename_message), + ); } } if potential_assoc_types.len() == assoc_items.len() { @@ -642,8 +758,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // extra type arguments present. A suggesting to replace the generic args with // associated types is already emitted. already_has_generics_args_suggestion = true; - } else if let (Ok(snippet), false) = - (tcx.sess.source_map().span_to_snippet(*span), dupes) + } else if let (Ok(snippet), false, false) = + (tcx.sess.source_map().span_to_snippet(*span), dupes, shadows) { let types: Vec<_> = assoc_items.iter().map(|item| format!("{} = Type", item.name)).collect(); @@ -725,6 +841,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.span_help(where_constraints, where_msg); } } + err.emit(); } } diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index d29a27ece..b495b00ec 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -243,6 +243,31 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( match (args_iter.peek(), params.peek()) { (Some(&arg), Some(¶m)) => { match (arg, ¶m.kind, arg_count.explicit_late_bound) { + ( + GenericArg::Const(hir::ConstArg { + is_desugared_from_effects: true, + .. + }), + GenericParamDefKind::Const { is_host_effect: false, .. } + | GenericParamDefKind::Type { .. } + | GenericParamDefKind::Lifetime, + _, + ) => { + // SPECIAL CASE FOR DESUGARED EFFECT PARAMS + // This comes from the following example: + // + // ``` + // #[const_trait] + // pub trait PartialEq<Rhs: ?Sized = Self> {} + // impl const PartialEq for () {} + // ``` + // + // Since this is a const impl, we need to insert a host arg at the end of + // `PartialEq`'s generics, but this errors since `Rhs` isn't specified. + // To work around this, we infer all arguments until we reach the host param. + args.push(ctx.inferred_kind(Some(&args), param, infer_args)); + params.next(); + } (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _) | ( GenericArg::Type(_) | GenericArg::Infer(_), @@ -636,7 +661,7 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes( args.args[0].hir_id(), multispan, msg, - |lint| lint, + |_| {}, ); } diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs index bc57bbcca..9afb04b74 100644 --- a/compiler/rustc_hir_analysis/src/astconv/lint.rs +++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs @@ -24,7 +24,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .. }), .. - }) = tcx.hir().get_by_def_id(parent_id) + }) = tcx.hir_node_by_def_id(parent_id) && self_ty.hir_id == impl_self_ty.hir_id { if !of_trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) { @@ -106,7 +106,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); } // check if the impl trait that we are considering is a impl of a local trait - self.maybe_lint_blanket_trait_impl(&self_ty, &mut diag); + self.maybe_lint_blanket_trait_impl(self_ty, &mut diag); diag.stash(self_ty.span, StashKey::TraitMissingMethod); } else { let msg = "trait objects without an explicit `dyn` are deprecated"; @@ -121,8 +121,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { sugg, Applicability::MachineApplicable, ); - self.maybe_lint_blanket_trait_impl(&self_ty, lint); - lint + self.maybe_lint_blanket_trait_impl(self_ty, lint); }, ); } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 2fcb45ef8..6f8e80172 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -18,29 +18,30 @@ use crate::require_c_abi_if_c_variadic; use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{ - struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, FatalError, - MultiSpan, + error_code, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, + FatalError, MultiSpan, }; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{walk_generics, Visitor as _}; use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin}; -use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{ - self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, + self, Const, GenericArgKind, GenericArgsRef, IsSuggestable, ParamEnv, Ty, TyCtxt, + TypeVisitableExt, }; use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; +use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::{sym, BytePos, Span, DUMMY_SP}; use rustc_target::spec::abi; use rustc_trait_selection::traits::wf::object_region_bounds; -use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCtxt}; -use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_trait_selection::traits::{self, ObligationCtxt}; use std::fmt::Display; use std::slice; @@ -162,7 +163,7 @@ struct ConvertedBinding<'a, 'tcx> { #[derive(Debug)] enum ConvertedBindingKind<'a, 'tcx> { - Equality(ty::Term<'tcx>), + Equality(Spanned<ty::Term<'tcx>>), Constraint(&'a [hir::GenericBound<'a>]), } @@ -239,7 +240,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def: Option<&ty::GenericParamDef>, ) -> ty::Region<'tcx> { let tcx = self.tcx(); - let lifetime_name = |def_id| tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id)); + let lifetime_name = |def_id| tcx.hir().name(tcx.local_def_id_to_hir_id(def_id)); match tcx.named_bound_var(lifetime.hir_id) { Some(rbv::ResolvedArg::StaticLifetime) => tcx.lifetimes.re_static, @@ -250,7 +251,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { var: ty::BoundVar::from_u32(index), kind: ty::BrNamed(def_id, name), }; - ty::Region::new_late_bound(tcx, debruijn, br) + ty::Region::new_bound(tcx, debruijn, br) } Some(rbv::ResolvedArg::EarlyBound(def_id)) => { @@ -258,12 +259,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let item_def_id = tcx.hir().ty_param_owner(def_id.expect_local()); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; - ty::Region::new_early_bound(tcx, ty::EarlyBoundRegion { def_id, index, name }) + ty::Region::new_early_param(tcx, ty::EarlyParamRegion { def_id, index, name }) } Some(rbv::ResolvedArg::Free(scope, id)) => { let name = lifetime_name(id.expect_local()); - ty::Region::new_free(tcx, scope, ty::BrNamed(id, name)) + ty::Region::new_late_param(tcx, scope, ty::BrNamed(id, name)) // (*) -- not late-bound, won't change } @@ -476,7 +477,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty::Const::new_misc_error(tcx, ty).into() } } - _ => unreachable!(), + (kind, arg) => span_bug!( + self.span, + "mismatched path argument for kind {kind:?}: found arg {arg:?}" + ), } } @@ -595,12 +599,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .map(|binding| { let kind = match &binding.kind { hir::TypeBindingKind::Equality { term } => match term { - hir::Term::Ty(ty) => { - ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty).into()) - } + hir::Term::Ty(ty) => ConvertedBindingKind::Equality(respan( + ty.span, + self.ast_ty_to_ty(ty).into(), + )), hir::Term::Const(c) => { + let span = self.tcx().def_span(c.def_id); let c = Const::from_anon_const(self.tcx(), c.def_id); - ConvertedBindingKind::Equality(c.into()) + ConvertedBindingKind::Equality(respan(span, c.into())) } }, hir::TypeBindingKind::Constraint { bounds } => { @@ -672,36 +678,57 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) } - fn instantiate_poly_trait_ref_inner( + /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct + /// a full trait reference. The resulting trait reference is returned. This may also generate + /// auxiliary bounds, which are added to `bounds`. + /// + /// Example: + /// + /// ```ignore (illustrative) + /// poly_trait_ref = Iterator<Item = u32> + /// self_ty = Foo + /// ``` + /// + /// this would return `Foo: Iterator` and add `<Foo as Iterator>::Item = u32` into `bounds`. + /// + /// **A note on binders:** against our usual convention, there is an implied binder around + /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions. + /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>` + /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be + /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, + /// however. + #[instrument(level = "debug", skip(self, span, constness, bounds, speculative))] + pub(crate) fn instantiate_poly_trait_ref( &self, - hir_id: hir::HirId, + trait_ref: &hir::TraitRef<'_>, span: Span, - binding_span: Option<Span>, constness: ty::BoundConstness, polarity: ty::ImplPolarity, + self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, speculative: bool, - trait_ref_span: Span, - trait_def_id: DefId, - trait_segment: &hir::PathSegment<'_>, - args: &GenericArgs<'_>, - infer_args: bool, - self_ty: Ty<'tcx>, only_self_bounds: OnlySelfBounds, ) -> GenericArgCountResult { + let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); + let trait_segment = trait_ref.path.segments.last().unwrap(); + let args = trait_segment.args(); + + self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {}); + self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false); + let (generic_args, arg_count) = self.create_args_for_ast_path( - trait_ref_span, + trait_ref.path.span, trait_def_id, &[], trait_segment, args, - infer_args, + trait_segment.infer_args, Some(self_ty), constness, ); let tcx = self.tcx(); - let bound_vars = tcx.late_bound_vars(hir_id); + let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id); debug!(?bound_vars); let assoc_bindings = self.create_assoc_bindings_for_generic_args(args); @@ -720,21 +747,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // since we should have emitten an error for them earlier, and they will // not be well-formed! if polarity == ty::ImplPolarity::Negative { - self.tcx() - .sess - .delay_span_bug(binding.span, "negative trait bounds should not have bindings"); + self.tcx().sess.span_delayed_bug( + binding.span, + "negative trait bounds should not have bindings", + ); continue; } // Specify type to assert that error was already reported in `Err` case. let _: Result<_, ErrorGuaranteed> = self.add_predicates_for_ast_type_binding( - hir_id, + trait_ref.hir_ref_id, poly_trait_ref, binding, bounds, speculative, &mut dup_bindings, - binding_span.unwrap_or(binding.span), + binding.span, constness, only_self_bounds, polarity, @@ -745,102 +773,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { arg_count } - /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct - /// a full trait reference. The resulting trait reference is returned. This may also generate - /// auxiliary bounds, which are added to `bounds`. - /// - /// Example: - /// - /// ```ignore (illustrative) - /// poly_trait_ref = Iterator<Item = u32> - /// self_ty = Foo - /// ``` - /// - /// this would return `Foo: Iterator` and add `<Foo as Iterator>::Item = u32` into `bounds`. - /// - /// **A note on binders:** against our usual convention, there is an implied bounder around - /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions. - /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>` - /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be - /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, - /// however. - #[instrument(level = "debug", skip(self, span, constness, bounds, speculative))] - pub(crate) fn instantiate_poly_trait_ref( - &self, - trait_ref: &hir::TraitRef<'_>, - span: Span, - constness: ty::BoundConstness, - polarity: ty::ImplPolarity, - self_ty: Ty<'tcx>, - bounds: &mut Bounds<'tcx>, - speculative: bool, - only_self_bounds: OnlySelfBounds, - ) -> GenericArgCountResult { - let hir_id = trait_ref.hir_ref_id; - let binding_span = None; - let trait_ref_span = trait_ref.path.span; - let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); - let trait_segment = trait_ref.path.segments.last().unwrap(); - let args = trait_segment.args(); - let infer_args = trait_segment.infer_args; - - self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1.iter(), |_| {}); - self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment, false); - - self.instantiate_poly_trait_ref_inner( - hir_id, - span, - binding_span, - constness, - polarity, - bounds, - speculative, - trait_ref_span, - trait_def_id, - trait_segment, - args, - infer_args, - self_ty, - only_self_bounds, - ) - } - - pub(crate) fn instantiate_lang_item_trait_ref( - &self, - lang_item: hir::LangItem, - span: Span, - hir_id: hir::HirId, - args: &GenericArgs<'_>, - self_ty: Ty<'tcx>, - bounds: &mut Bounds<'tcx>, - only_self_bounds: OnlySelfBounds, - ) { - let binding_span = Some(span); - let constness = ty::BoundConstness::NotConst; - let speculative = false; - let trait_ref_span = span; - let trait_def_id = self.tcx().require_lang_item(lang_item, Some(span)); - let trait_segment = &hir::PathSegment::invalid(); - let infer_args = false; - - self.instantiate_poly_trait_ref_inner( - hir_id, - span, - binding_span, - constness, - ty::ImplPolarity::Positive, - bounds, - speculative, - trait_ref_span, - trait_def_id, - trait_segment, - args, - infer_args, - self_ty, - only_self_bounds, - ); - } - fn ast_path_to_mono_trait_ref( &self, span: Span, @@ -945,7 +877,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Applicability::MachineApplicable, ); } else { - match (types, traits) { + let mut types = types.to_vec(); + types.sort(); + let mut traits = traits.to_vec(); + traits.sort(); + match (&types[..], &traits[..]) { ([], []) => { err.span_suggestion_verbose( span, @@ -1051,7 +987,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("find_bound_for_assoc_item: predicates={:#?}", predicates); let param_name = tcx.hir().ty_param_name(ty_param_def_id); - self.one_bound_for_assoc_type( + self.one_bound_for_assoc_item( || { traits::transitive_bounds_that_define_assoc_item( tcx, @@ -1063,6 +999,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }, param_name, Some(ty_param_def_id), + ty::AssocKind::Type, assoc_name, span, None, @@ -1071,48 +1008,45 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Checks that `bounds` contains exactly one element and reports appropriate // errors otherwise. - #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, is_equality), ret)] - fn one_bound_for_assoc_type<I>( + #[instrument(level = "debug", skip(self, all_candidates, ty_param_name, binding), ret)] + fn one_bound_for_assoc_item<I>( &self, all_candidates: impl Fn() -> I, ty_param_name: impl Display, ty_param_def_id: Option<LocalDefId>, + assoc_kind: ty::AssocKind, assoc_name: Ident, span: Span, - is_equality: Option<ty::Term<'tcx>>, + binding: Option<&ConvertedBinding<'_, 'tcx>>, ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> where I: Iterator<Item = ty::PolyTraitRef<'tcx>>, { + let tcx = self.tcx(); + let mut matching_candidates = all_candidates().filter(|r| { - self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Type, assoc_name) - }); - let mut const_candidates = all_candidates().filter(|r| { - self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Const, assoc_name) + self.trait_defines_associated_item_named(r.def_id(), assoc_kind, assoc_name) }); - let (mut bound, mut next_cand) = match (matching_candidates.next(), const_candidates.next()) - { - (Some(bound), _) => (bound, matching_candidates.next()), - (None, Some(bound)) => (bound, const_candidates.next()), - (None, None) => { - let reported = self.complain_about_assoc_type_not_found( - all_candidates, - &ty_param_name.to_string(), - ty_param_def_id, - assoc_name, - span, - ); - return Err(reported); - } + let Some(mut bound) = matching_candidates.next() else { + let reported = self.complain_about_assoc_item_not_found( + all_candidates, + &ty_param_name.to_string(), + ty_param_def_id, + assoc_kind, + assoc_name, + span, + binding, + ); + return Err(reported); }; debug!(?bound); // look for a candidate that is not the same as our first bound, disregarding // whether the bound is const. + let mut next_cand = matching_candidates.next(); while let Some(mut bound2) = next_cand { debug!(?bound2); - let tcx = self.tcx(); if bound2.bound_vars() != bound.bound_vars() { break; } @@ -1133,7 +1067,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .map(|(n, arg)| if host_index == n { tcx.consts.true_.into() } else { arg }); if unconsted_args.eq(bound2.skip_binder().args.iter()) { - next_cand = matching_candidates.next().or_else(|| const_candidates.next()); + next_cand = matching_candidates.next(); } else { break; } @@ -1142,51 +1076,53 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(bound2) = next_cand { debug!(?bound2); - let bounds = IntoIterator::into_iter([bound, bound2]).chain(matching_candidates); - let mut err = if is_equality.is_some() { - // More specific Error Index entry. - struct_span_err!( - self.tcx().sess, - span, - E0222, - "ambiguous associated type `{}` in bounds of `{}`", - assoc_name, - ty_param_name - ) - } else { - struct_span_err!( - self.tcx().sess, - span, - E0221, - "ambiguous associated type `{}` in bounds of `{}`", - assoc_name, - ty_param_name - ) - }; - err.span_label(span, format!("ambiguous associated type `{assoc_name}`")); + let assoc_kind_str = assoc_kind_str(assoc_kind); + let ty_param_name = &ty_param_name.to_string(); + let mut err = tcx.sess.create_err(crate::errors::AmbiguousAssocItem { + span, + assoc_kind: assoc_kind_str, + assoc_name, + ty_param_name, + }); + // Provide a more specific error code index entry for equality bindings. + err.code( + if let Some(binding) = binding + && let ConvertedBindingKind::Equality(_) = binding.kind + { + error_code!(E0222) + } else { + error_code!(E0221) + }, + ); + // FIXME(#97583): Resugar equality bounds to type/const bindings. + // FIXME: Turn this into a structured, translateable & more actionable suggestion. let mut where_bounds = vec![]; - for bound in bounds { + for bound in [bound, bound2].into_iter().chain(matching_candidates) { let bound_id = bound.def_id(); - let bound_span = self - .tcx() + let bound_span = tcx .associated_items(bound_id) - .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, bound_id) - .and_then(|item| self.tcx().hir().span_if_local(item.def_id)); + .find_by_name_and_kind(tcx, assoc_name, assoc_kind, bound_id) + .and_then(|item| tcx.hir().span_if_local(item.def_id)); if let Some(bound_span) = bound_span { err.span_label( bound_span, - format!( - "ambiguous `{assoc_name}` from `{}`", - bound.print_only_trait_path(), - ), + format!("ambiguous `{assoc_name}` from `{}`", bound.print_trait_sugared(),), ); - if let Some(constraint) = &is_equality { - where_bounds.push(format!( - " T: {trait}::{assoc_name} = {constraint}", - trait=bound.print_only_trait_path(), - )); + if let Some(binding) = binding { + match binding.kind { + ConvertedBindingKind::Equality(term) => { + // FIXME(#97583): This isn't syntactically well-formed! + where_bounds.push(format!( + " T: {trait}::{assoc_name} = {term}", + trait = bound.print_only_trait_path(), + term = term.node, + )); + } + // FIXME: Provide a suggestion. + ConvertedBindingKind::Constraint(_bounds) => {} + } } else { err.span_suggestion_verbose( span.with_hi(assoc_name.span.lo()), @@ -1197,7 +1133,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } else { err.note(format!( - "associated type `{ty_param_name}` could derive from `{}`", + "associated {assoc_kind_str} `{assoc_name}` could derive from `{}`", bound.print_only_trait_path(), )); } @@ -1218,46 +1154,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Ok(bound) } - #[instrument(level = "debug", skip(self, all_candidates, ty_name), ret)] - fn one_bound_for_assoc_method( - &self, - all_candidates: impl Iterator<Item = ty::PolyTraitRef<'tcx>>, - ty_name: impl Display, - assoc_name: Ident, - span: Span, - ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> { - let mut matching_candidates = all_candidates.filter(|r| { - self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Fn, assoc_name) - }); - - let candidate = match matching_candidates.next() { - Some(candidate) => candidate, - None => { - return Err(self.tcx().sess.emit_err( - crate::errors::ReturnTypeNotationMissingMethod { - span, - ty_name: ty_name.to_string(), - assoc_name: assoc_name.name, - }, - )); - } - }; - - if let Some(conflicting_candidate) = matching_candidates.next() { - return Err(self.tcx().sess.emit_err( - crate::errors::ReturnTypeNotationConflictingBound { - span, - ty_name: ty_name.to_string(), - assoc_name: assoc_name.name, - first_bound: candidate.print_only_trait_path(), - second_bound: conflicting_candidate.print_only_trait_path(), - }, - )); - } - - Ok(candidate) - } - // Create a type from a path to an associated type or to an enum variant. // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C` // and item_segment is the path segment for `D`. We return a type and a def for @@ -1415,11 +1311,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // trait reference. let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else { // A cycle error occurred, most likely. - let guar = tcx.sess.delay_span_bug(span, "expected cycle error"); + let guar = tcx.sess.span_delayed_bug(span, "expected cycle error"); return Err(guar); }; - self.one_bound_for_assoc_type( + self.one_bound_for_assoc_item( || { traits::supertraits( tcx, @@ -1428,6 +1324,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }, kw::SelfUpper, None, + ty::AssocKind::Type, assoc_ident, span, None, @@ -1508,15 +1405,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; let trait_did = bound.def_id(); - let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, trait_did) - else { - // Assume that if it's not matched, there must be a const defined with the same name - // but it was used in a type position. - let msg = format!("found associated const `{assoc_ident}` when type was expected"); - let guar = tcx.sess.struct_span_err(span, msg).emit(); - return Err(guar); - }; - + let assoc_ty_did = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, trait_did).unwrap(); let ty = self.projected_ty_from_poly_trait_ref(span, assoc_ty_did, assoc_segment, bound); if let Some(variant_def_id) = variant_resolution { @@ -1545,8 +1434,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { format!("<{} as {}>::{}", qself_ty, tcx.item_name(trait_did), assoc_ident), Applicability::MachineApplicable, ); - - lint }, ); } @@ -1602,134 +1489,110 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // FIXME(inherent_associated_types): Acquiring the ParamEnv this early leads to cycle errors // when inside of an ADT (#108491) or where clause. let param_env = tcx.param_env(block.owner); - let cause = ObligationCause::misc(span, block.owner.def_id); - - let mut fulfillment_errors = Vec::new(); - let mut applicable_candidates: Vec<_> = infcx.probe(|_| { - // Regions are not considered during selection. - let self_ty = self_ty - .fold_with(&mut BoundVarEraser { tcx, universe: infcx.create_next_universe() }); - - struct BoundVarEraser<'tcx> { - tcx: TyCtxt<'tcx>, - universe: ty::UniverseIndex, - } - // FIXME(non_lifetime_binders): Don't assign the same universe to each placeholder. - impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarEraser<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } + let mut universes = if self_ty.has_escaping_bound_vars() { + vec![None; self_ty.outer_exclusive_binder().as_usize()] + } else { + vec![] + }; - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if r.is_late_bound() { self.tcx.lifetimes.re_erased } else { r } - } + let (impl_, (assoc_item, def_scope)) = + crate::traits::project::with_replaced_escaping_bound_vars( + infcx, + &mut universes, + self_ty, + |self_ty| { + self.select_inherent_assoc_type_candidates( + infcx, name, span, self_ty, param_env, candidates, + ) + }, + )?; + + self.check_assoc_ty(assoc_item, name, def_scope, block, span); + + // FIXME(fmease): Currently creating throwaway `parent_args` to please + // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to + // not require the parent args logic. + let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_); + let args = self.create_args_for_associated_item(span, assoc_item, segment, parent_args); + let args = tcx.mk_args_from_iter( + std::iter::once(ty::GenericArg::from(self_ty)) + .chain(args.into_iter().skip(parent_args.len())), + ); - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match *ty.kind() { - ty::Bound(_, bv) => Ty::new_placeholder( - self.tcx, - ty::PlaceholderType { universe: self.universe, bound: bv }, - ), - _ => ty.super_fold_with(self), - } - } + let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args)); - fn fold_const( - &mut self, - ct: ty::Const<'tcx>, - ) -> <TyCtxt<'tcx> as rustc_type_ir::Interner>::Const { - assert!(!ct.ty().has_escaping_bound_vars()); - - match ct.kind() { - ty::ConstKind::Bound(_, bv) => ty::Const::new_placeholder( - self.tcx, - ty::PlaceholderConst { universe: self.universe, bound: bv }, - ct.ty(), - ), - _ => ct.super_fold_with(self), - } - } - } + Ok(Some((ty, assoc_item))) + } - let InferOk { value: self_ty, obligations } = - infcx.at(&cause, param_env).normalize(self_ty); + fn select_inherent_assoc_type_candidates( + &self, + infcx: &InferCtxt<'tcx>, + name: Ident, + span: Span, + self_ty: Ty<'tcx>, + param_env: ParamEnv<'tcx>, + candidates: Vec<(DefId, (DefId, DefId))>, + ) -> Result<(DefId, (DefId, DefId)), ErrorGuaranteed> { + let tcx = self.tcx(); + let mut fulfillment_errors = Vec::new(); - candidates - .iter() - .copied() - .filter(|&(impl_, _)| { - infcx.probe(|_| { - let ocx = ObligationCtxt::new(&infcx); - ocx.register_obligations(obligations.clone()); - - let impl_args = infcx.fresh_args_for_item(span, impl_); - let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args); - let impl_ty = ocx.normalize(&cause, param_env, impl_ty); - - // Check that the self types can be related. - // FIXME(inherent_associated_types): Should we use `eq` here? Method probing uses - // `sup` for this situtation, too. What for? To constrain inference variables? - if ocx.sup(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() - { - return false; - } + let applicable_candidates: Vec<_> = candidates + .iter() + .copied() + .filter(|&(impl_, _)| { + infcx.probe(|_| { + let ocx = ObligationCtxt::new(infcx); + let self_ty = ocx.normalize(&ObligationCause::dummy(), param_env, self_ty); + + let impl_args = infcx.fresh_args_for_item(span, impl_); + let impl_ty = tcx.type_of(impl_).instantiate(tcx, impl_args); + let impl_ty = ocx.normalize(&ObligationCause::dummy(), param_env, impl_ty); + + // Check that the self types can be related. + if ocx.eq(&ObligationCause::dummy(), param_env, impl_ty, self_ty).is_err() { + return false; + } - // Check whether the impl imposes obligations we have to worry about. - let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args); - let impl_bounds = ocx.normalize(&cause, param_env, impl_bounds); - let impl_obligations = traits::predicates_for_generics( - |_, _| cause.clone(), - param_env, - impl_bounds, - ); - ocx.register_obligations(impl_obligations); + // Check whether the impl imposes obligations we have to worry about. + let impl_bounds = tcx.predicates_of(impl_).instantiate(tcx, impl_args); + let impl_bounds = + ocx.normalize(&ObligationCause::dummy(), param_env, impl_bounds); + let impl_obligations = traits::predicates_for_generics( + |_, _| ObligationCause::dummy(), + param_env, + impl_bounds, + ); + ocx.register_obligations(impl_obligations); - let mut errors = ocx.select_where_possible(); - if !errors.is_empty() { - fulfillment_errors.append(&mut errors); - return false; - } + let mut errors = ocx.select_where_possible(); + if !errors.is_empty() { + fulfillment_errors.append(&mut errors); + return false; + } - true - }) + true }) - .collect() - }); + }) + .collect(); - if applicable_candidates.len() > 1 { - return Err(self.complain_about_ambiguous_inherent_assoc_type( + match &applicable_candidates[..] { + &[] => Err(self.complain_about_inherent_assoc_type_not_found( name, - applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(), + self_ty, + candidates, + fulfillment_errors, span, - )); - } + )), - if let Some((impl_, (assoc_item, def_scope))) = applicable_candidates.pop() { - self.check_assoc_ty(assoc_item, name, def_scope, block, span); - - // FIXME(fmease): Currently creating throwaway `parent_args` to please - // `create_args_for_associated_item`. Modify the latter instead (or sth. similar) to - // not require the parent args logic. - let parent_args = ty::GenericArgs::identity_for_item(tcx, impl_); - let args = self.create_args_for_associated_item(span, assoc_item, segment, parent_args); - let args = tcx.mk_args_from_iter( - std::iter::once(ty::GenericArg::from(self_ty)) - .chain(args.into_iter().skip(parent_args.len())), - ); + &[applicable_candidate] => Ok(applicable_candidate), - let ty = Ty::new_alias(tcx, ty::Inherent, ty::AliasTy::new(tcx, assoc_item, args)); - - return Ok(Some((ty, assoc_item))); + &[_, ..] => Err(self.complain_about_ambiguous_inherent_assoc_type( + name, + applicable_candidates.into_iter().map(|(_, (candidate, _))| candidate).collect(), + span, + )), } - - Err(self.complain_about_inherent_assoc_type_not_found( - name, - self_ty, - candidates, - fulfillment_errors, - span, - )) } fn lookup_assoc_ty( @@ -1753,8 +1616,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); let (ident, def_scope) = tcx.adjust_ident_and_get_scope(name, scope, block); - // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead - // of calling `find_by_name_and_kind`. + // We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()` + // instead of calling `filter_by_name_and_kind` which would needlessly normalize the + // `ident` again and again. let item = tcx.associated_items(scope).in_definition_order().find(|i| { i.kind.namespace() == Namespace::TypeNS && i.ident(tcx).normalize_to_macros_2_0() == ident @@ -1869,7 +1733,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let parent_def_id = def_id .as_local() - .map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id)) + .map(|def_id| tcx.local_def_id_to_hir_id(def_id)) .map(|hir_id| tcx.hir().get_parent_item(hir_id).to_def_id()); debug!("qpath_to_ty: parent_def_id={:?}", parent_def_id); @@ -1973,7 +1837,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { types_and_spans[..types_and_spans.len() - 1] .iter() .map(|(x, _)| x.as_str()) - .intersperse(&", ") + .intersperse(", ") .collect::<String>() ), [(only, _)] => only.to_string(), @@ -2008,7 +1872,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { "s", ), [only] => (only.to_string(), ""), - [] => unreachable!(), + [] => unreachable!("expected at least one generic to prohibit"), }; let last_span = *arg_spans.last().unwrap(); let span: MultiSpan = arg_spans.into(); @@ -2396,7 +2260,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let e = self .tcx() .sess - .delay_span_bug(path.span, "path with `Res::Err` but no error emitted"); + .span_delayed_bug(path.span, "path with `Res::Err` but no error emitted"); self.set_tainted_by_errors(e); Ty::new_error(self.tcx(), e) } @@ -2543,7 +2407,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .map(|(ty, _, _)| ty) .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) } - &hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => { + &hir::TyKind::Path(hir::QPath::LangItem(lang_item, span)) => { let def_id = tcx.require_lang_item(lang_item, Some(span)); let (args, _) = self.create_args_for_ast_path( span, @@ -2617,8 +2481,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(i) = (param.index as usize).checked_sub(generics.count() - lifetimes.len()) { // Resolve our own lifetime parameters. - let GenericParamDefKind::Lifetime { .. } = param.kind else { bug!() }; - let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] else { bug!() }; + let GenericParamDefKind::Lifetime { .. } = param.kind else { + span_bug!( + tcx.def_span(param.def_id), + "only expected lifetime for opaque's own generics, got {:?}", + param.kind + ); + }; + let hir::GenericArg::Lifetime(lifetime) = &lifetimes[i] else { + bug!( + "expected lifetime argument for param {param:?}, found {:?}", + &lifetimes[i] + ) + }; self.ast_region_to_region(lifetime, None).into() } else { tcx.mk_param_from_def(param) @@ -2777,7 +2652,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let hir = tcx.hir(); let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) = - hir.get(fn_hir_id) + tcx.hir_node(fn_hir_id) else { return None; }; @@ -2845,6 +2720,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// provided, if they provided one, and otherwise search the supertypes of trait bounds /// for region bounds. It may be that we can derive no bound at all, in which case /// we return `None`. + #[instrument(level = "debug", skip(self, span), ret)] fn compute_object_lifetime_bound( &self, span: Span, @@ -2853,8 +2729,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { let tcx = self.tcx(); - debug!("compute_opt_region_bound(existential_predicates={:?})", existential_predicates); - // No explicit region bound specified. Therefore, examine trait // bounds and see if we can derive region bounds from those. let derived_region_bounds = object_region_bounds(tcx, existential_predicates); @@ -2881,3 +2755,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Some(r) } } + +fn assoc_kind_str(kind: ty::AssocKind) -> &'static str { + match kind { + ty::AssocKind::Fn => "function", + ty::AssocKind::Const => "constant", + ty::AssocKind::Type => "type", + } +} diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 00ff3f836..dd5deb6f2 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -1,7 +1,7 @@ use crate::astconv::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds}; use crate::bounds::Bounds; use crate::errors::TraitObjectDeclaredWithNoTraits; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -14,7 +14,6 @@ use rustc_trait_selection::traits::error_reporting::report_object_safety_error; use rustc_trait_selection::traits::{self, astconv_object_safety_violations}; use smallvec::{smallvec, SmallVec}; -use std::collections::BTreeSet; use super::AstConv; @@ -74,7 +73,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { | ty::ClauseKind::ConstArgHasType(..) | ty::ClauseKind::WellFormed(_) | ty::ClauseKind::ConstEvaluatable(_) => { - bug!() + span_bug!(span, "did not expect {pred} clause in object bounds"); } } } @@ -107,6 +106,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait here instead: `trait NewTrait: {} {{}}`", regular_traits .iter() + // FIXME: This should `print_sugared`, but also needs to integrate projection bounds... .map(|t| t.trait_ref().print_only_trait_path().to_string()) .collect::<Vec<_>>() .join(" + "), @@ -148,8 +148,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - // Use a `BTreeSet` to keep output in a more consistent order. - let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default(); + let mut associated_types: FxIndexMap<Span, FxIndexSet<DefId>> = FxIndexMap::default(); let regular_traits_refs_spans = trait_bounds .into_iter() @@ -327,7 +326,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { false }); if references_self { - let guar = tcx.sess.delay_span_bug( + let guar = tcx.sess.span_delayed_bug( span, "trait object projection bounds reference `Self`", ); diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index 39db29504..5fc500f48 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -182,7 +182,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { } }; - let errors = fulfill_cx.select_where_possible(&self.infcx); + let errors = fulfill_cx.select_where_possible(self.infcx); if !errors.is_empty() { // This shouldn't happen, except for evaluate/fulfill mismatches, // but that's not a reason for an ICE (`predicate_may_hold` is conservative diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index e61ca232d..8413a1cc0 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1,5 +1,5 @@ use crate::check::intrinsicck::InlineAsmCtxt; -use crate::errors::{self, LinkageType}; +use crate::errors::LinkageType; use super::compare_impl_item::check_type_bounds; use super::compare_impl_item::{compare_impl_method, compare_impl_ty}; @@ -8,9 +8,8 @@ use rustc_attr as attr; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; -use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; +use rustc_hir::def_id::LocalModDefId; use rustc_hir::Node; -use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, TraitEngineExt as _}; use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; @@ -21,18 +20,15 @@ use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::{ - self, AdtDef, ParamEnv, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, - TypeVisitableExt, + AdtDef, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, }; use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; use rustc_span::symbol::sym; -use rustc_span::{self, Span}; use rustc_target::abi::FieldIdx; -use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; -use rustc_trait_selection::traits::{self, ObligationCtxt, TraitEngine, TraitEngineExt as _}; +use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _}; use rustc_type_ir::fold::TypeFoldable; use std::ops::ControlFlow; @@ -55,7 +51,7 @@ pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { hir_id, span, "use of calling convention not supported on this target", - |lint| lint, + |_| {}, ); } } @@ -130,7 +126,7 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b for field in &def.non_enum_variant().fields { let Ok(field_ty) = tcx.try_normalize_erasing_regions(param_env, field.ty(tcx, args)) else { - tcx.sess.delay_span_bug(span, "could not normalize field type"); + tcx.sess.span_delayed_bug(span, "could not normalize field type"); continue; }; @@ -151,7 +147,8 @@ fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> b return false; } else if field_ty.needs_drop(tcx, param_env) { // This should never happen. But we can get here e.g. in case of name resolution errors. - tcx.sess.delay_span_bug(span, "we should never accept maybe-dropping union fields"); + tcx.sess + .span_delayed_bug(span, "we should never accept maybe-dropping union fields"); } } } else { @@ -181,19 +178,19 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { } // Generic statics are rejected, but we still reach this case. Err(e) => { - tcx.sess.delay_span_bug(span, format!("{e:?}")); + tcx.sess.span_delayed_bug(span, format!("{e:?}")); return; } }; if layout.abi.is_uninhabited() { tcx.struct_span_lint_hir( UNINHABITED_STATIC, - tcx.hir().local_def_id_to_hir_id(def_id), + tcx.local_def_id_to_hir_id(def_id), span, "static of uninhabited type", |lint| { lint - .note("uninhabited statics cannot be initialized, and any access would be an immediate error") + .note("uninhabited statics cannot be initialized, and any access would be an immediate error"); }, ); } @@ -204,7 +201,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) { fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { let item = tcx.hir().item(id); let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else { - tcx.sess.delay_span_bug(item.span, "expected opaque item"); + tcx.sess.span_delayed_bug(item.span, "expected opaque item"); return; }; @@ -222,11 +219,11 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) { if tcx.type_of(item.owner_id.def_id).instantiate_identity().references_error() { return; } - if check_opaque_for_cycles(tcx, item.owner_id.def_id, args, span, &origin).is_err() { + if check_opaque_for_cycles(tcx, item.owner_id.def_id, args, span, origin).is_err() { return; } - let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin); + let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, origin); } /// Checks that an opaque type does not contain cycles. @@ -313,7 +310,7 @@ fn check_opaque_meets_bounds<'tcx>( Ok(()) => {} Err(ty_err) => { let ty_err = ty_err.to_string(tcx); - return Err(tcx.sess.delay_span_bug( + return Err(tcx.sess.span_delayed_bug( span, format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"), )); @@ -482,7 +479,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { match assoc_item.kind { ty::AssocKind::Fn => { let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi(); - fn_maybe_err(tcx, assoc_item.ident(tcx).span, abi); + forbid_intrinsic_abi(tcx, assoc_item.ident(tcx).span, abi); } ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => { let trait_args = GenericArgs::identity_for_item(tcx, id.owner_id); @@ -507,7 +504,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { let origin = tcx.opaque_type_origin(id.owner_id.def_id); if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin - && let hir::Node::TraitItem(trait_item) = tcx.hir().get_by_def_id(fn_def_id) + && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id) && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn() { // Skip opaques from RPIT in traits with no default body. @@ -518,7 +515,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { DefKind::TyAlias => { let pty_ty = tcx.type_of(id.owner_id).instantiate_identity(); let generics = tcx.generics_of(id.owner_id); - check_type_params_are_used(tcx, &generics, pty_ty); + check_type_params_are_used(tcx, generics, pty_ty); } DefKind::ForeignMod => { let it = tcx.hir().item(id); @@ -655,7 +652,7 @@ pub(super) fn check_specialization_validity<'tcx>( if !tcx.is_impl_trait_in_trait(impl_item) { report_forbidden_specialization(tcx, impl_item, parent_impl); } else { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( DUMMY_SP, format!("parent item: {parent_impl:?} not marked as default"), ); @@ -703,7 +700,7 @@ fn check_impl_items_against_trait<'tcx>( tcx.associated_item(trait_item_id) } else { // Checked in `associated_item`. - tcx.sess.delay_span_bug(tcx.def_span(impl_item), "missing associated item in trait"); + tcx.sess.span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait"); continue; }; match ty_impl_item.kind { @@ -753,8 +750,7 @@ fn check_impl_items_against_trait<'tcx>( leaf_def.as_ref().is_some_and(|node_item| !node_item.defining_node.is_from_trait()); if !is_implemented_here { - let full_impl_span = - tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id)); + let full_impl_span = tcx.hir().span_with_body(tcx.local_def_id_to_hir_id(impl_id)); match tcx.eval_default_body_stability(trait_item_id, full_impl_span) { EvalResult::Deny { feature, reason, issue, .. } => default_body_is_unstable( tcx, @@ -811,8 +807,7 @@ fn check_impl_items_against_trait<'tcx>( } if !missing_items.is_empty() { - let full_impl_span = - tcx.hir().span_with_body(tcx.hir().local_def_id_to_hir_id(impl_id)); + let full_impl_span = tcx.hir().span_with_body(tcx.local_def_id_to_hir_id(impl_id)); missing_items_err(tcx, impl_id, &missing_items, full_impl_span); } @@ -900,7 +895,7 @@ pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) { let repr = def.repr(); if repr.packed() { for attr in tcx.get_attrs(def.did(), sym::repr) { - for r in attr::parse_repr_attr(&tcx.sess, attr) { + for r in attr::parse_repr_attr(tcx.sess, attr) { if let attr::ReprPacked(pack) = r && let Some(repr_pack) = repr.pack && pack as u64 != repr_pack.bytes() @@ -1083,7 +1078,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) if non_trivial_count > 0 || prev_non_exhaustive_1zst { tcx.struct_span_lint_hir( REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, - tcx.hir().local_def_id_to_hir_id(adt.did().expect_local()), + tcx.local_def_id_to_hir_id(adt.did().expect_local()), span, "zero-sized fields in `repr(transparent)` cannot \ contain external non-exhaustive types", @@ -1098,7 +1093,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) "this {descr} contains `{field_ty}`, which {note}, \ and makes it not a breaking change to become \ non-zero-sized in the future." - )) + )); }, ) } else { @@ -1150,8 +1145,8 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) { let has_disr = |var: &ty::VariantDef| matches!(var.discr, ty::VariantDiscr::Explicit(_)); let has_non_units = def.variants().iter().any(|var| !is_unit(var)); - let disr_units = def.variants().iter().any(|var| is_unit(&var) && has_disr(&var)); - let disr_non_unit = def.variants().iter().any(|var| !is_unit(&var) && has_disr(&var)); + let disr_units = def.variants().iter().any(|var| is_unit(var) && has_disr(var)); + let disr_non_unit = def.variants().iter().any(|var| !is_unit(var) && has_disr(var)); if disr_non_unit || (disr_units && has_non_units) { let mut err = struct_span_err!( @@ -1178,7 +1173,7 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) ty::VariantDiscr::Explicit(discr_def_id) => { // In the case the discriminant is both a duplicate and overflowed, let the user know if let hir::Node::AnonConst(expr) = - tcx.hir().get_by_def_id(discr_def_id.expect_local()) + tcx.hir_node_by_def_id(discr_def_id.expect_local()) && let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind && let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node && *lit_value != dis.val @@ -1451,7 +1446,7 @@ fn opaque_type_cycle_error( label_match(capture.place.ty(), capture.get_path_span(tcx)); } // Label any coroutine locals that capture the opaque - if let DefKind::Coroutine = tcx.def_kind(closure_def_id) + if tcx.is_coroutine(closure_def_id) && let Some(coroutine_layout) = tcx.mir_coroutine_witnesses(closure_def_id) { for interior_ty in &coroutine_layout.field_tys { @@ -1468,8 +1463,11 @@ fn opaque_type_cycle_error( err.emit() } -pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) { - debug_assert!(matches!(tcx.def_kind(def_id), DefKind::Coroutine)); +pub(super) fn check_coroutine_obligations( + tcx: TyCtxt<'_>, + def_id: LocalDefId, +) -> Result<(), ErrorGuaranteed> { + debug_assert!(tcx.is_coroutine(def_id.to_def_id())); let typeck = tcx.typeck(def_id); let param_env = tcx.param_env(def_id); @@ -1482,8 +1480,9 @@ pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) { // typeck writeback gives us predicates with their regions erased. // As borrowck already has checked lifetimes, we do not need to do it again. .ignoring_regions() - // Bind opaque types to `def_id` as they should have been checked by borrowck. - .with_opaque_type_inference(DefiningAnchor::Bind(def_id)) + // Bind opaque types to type checking root, as they should have been checked by borrowck, + // but may show up in some cases, like when (root) obligations are stalled in the new solver. + .with_opaque_type_inference(DefiningAnchor::Bind(typeck.hir_owner.def_id)) .build(); let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx); @@ -1513,6 +1512,16 @@ pub(super) fn check_coroutine_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) { let errors = fulfillment_cx.select_all_or_error(&infcx); debug!(?errors); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(errors); + return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); } + + // Check that any hidden types found when checking these stalled coroutine obligations + // are valid. + for (key, ty) in infcx.take_opaque_types() { + let hidden_type = infcx.resolve_vars_if_possible(ty.hidden_type); + let key = infcx.resolve_vars_if_possible(key); + sanity_check_found_hidden_type(tcx, key, hidden_type)?; + } + + Ok(()) } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 857515f97..264868fdf 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2,9 +2,7 @@ use super::potentially_plural_count; use crate::errors::LifetimesOrBoundsMismatchOnTrait; use hir::def_id::{DefId, LocalDefId}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_errors::{ - pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed, MultiSpan, -}; +use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; @@ -50,13 +48,7 @@ pub(super) fn compare_impl_method<'tcx>( let _: Result<_, ErrorGuaranteed> = try { check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?; - compare_method_predicate_entailment( - tcx, - impl_m, - trait_m, - impl_trait_ref, - CheckImpliedWfMode::Check, - )?; + compare_method_predicate_entailment(tcx, impl_m, trait_m, impl_trait_ref)?; refine::check_refining_return_position_impl_trait_in_trait( tcx, impl_m, @@ -170,7 +162,6 @@ fn compare_method_predicate_entailment<'tcx>( impl_m: ty::AssocItem, trait_m: ty::AssocItem, impl_trait_ref: ty::TraitRef<'tcx>, - check_implied_wf: CheckImpliedWfMode, ) -> Result<(), ErrorGuaranteed> { let trait_to_impl_args = impl_trait_ref.args; @@ -307,7 +298,7 @@ fn compare_method_predicate_entailment<'tcx>( debug!(?impl_sig, ?trait_sig, ?terr, "sub_types failed"); let emitted = report_trait_method_mismatch( - &infcx, + infcx, cause, terr, (trait_m, trait_sig), @@ -317,10 +308,10 @@ fn compare_method_predicate_entailment<'tcx>( return Err(emitted); } - if check_implied_wf == CheckImpliedWfMode::Check && !(impl_sig, trait_sig).references_error() { + if !(impl_sig, trait_sig).references_error() { // Select obligations to make progress on inference before processing // the wf obligation below. - // FIXME(-Ztrait-solver=next): Not needed when the hack below is removed. + // FIXME(-Znext-solver): Not needed when the hack below is removed. let errors = ocx.select_where_possible(); if !errors.is_empty() { let reported = infcx.err_ctxt().report_fulfillment_errors(errors); @@ -333,8 +324,9 @@ fn compare_method_predicate_entailment<'tcx>( // trigger the lint. Instead, let's only consider type outlives and // region outlives obligations. // - // FIXME(-Ztrait-solver=next): Try removing this hack again once - // the new solver is stable. + // FIXME(-Znext-solver): Try removing this hack again once the new + // solver is stable. We should just be able to register a WF pred for + // the fn sig. let mut wf_args: smallvec::SmallVec<[_; 4]> = unnormalized_impl_sig.inputs_and_output.iter().map(|ty| ty.into()).collect(); // Annoyingly, asking for the WF predicates of an array (with an unevaluated const (only?)) @@ -357,7 +349,7 @@ fn compare_method_predicate_entailment<'tcx>( // We need to register Projection oblgiations too, because we may end up with // an implied `X::Item: 'a`, which gets desugared into `X::Item = ?0`, `?0: 'a`. // If we only register the region outlives obligation, this leads to an unconstrained var. - // See `implied_bounds_entailment_alias_var` test. + // See `implied_bounds_entailment_alias_var.rs` test. ty::PredicateKind::Clause( ty::ClauseKind::RegionOutlives(..) | ty::ClauseKind::TypeOutlives(..) @@ -378,26 +370,8 @@ fn compare_method_predicate_entailment<'tcx>( // version. let errors = ocx.select_all_or_error(); if !errors.is_empty() { - match check_implied_wf { - CheckImpliedWfMode::Check => { - let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id); - return compare_method_predicate_entailment( - tcx, - impl_m, - trait_m, - impl_trait_ref, - CheckImpliedWfMode::Skip, - ) - .map(|()| { - // If the skip-mode was successful, emit a lint. - emit_implied_wf_lint(infcx.tcx, impl_m, impl_m_hir_id, vec![]); - }); - } - CheckImpliedWfMode::Skip => { - let reported = infcx.err_ctxt().report_fulfillment_errors(errors); - return Err(reported); - } - } + let reported = infcx.err_ctxt().report_fulfillment_errors(errors); + return Err(reported); } // Finally, resolve all regions. This catches wily misuses of @@ -408,119 +382,14 @@ fn compare_method_predicate_entailment<'tcx>( ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { - // FIXME(compiler-errors): This can be simplified when IMPLIED_BOUNDS_ENTAILMENT - // becomes a hard error (i.e. ideally we'd just call `resolve_regions_and_report_errors` - let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id); - match check_implied_wf { - CheckImpliedWfMode::Check => { - return compare_method_predicate_entailment( - tcx, - impl_m, - trait_m, - impl_trait_ref, - CheckImpliedWfMode::Skip, - ) - .map(|()| { - let bad_args = extract_bad_args_for_implies_lint( - tcx, - &errors, - (trait_m, trait_sig), - // Unnormalized impl sig corresponds to the HIR types written - (impl_m, unnormalized_impl_sig), - impl_m_hir_id, - ); - // If the skip-mode was successful, emit a lint. - emit_implied_wf_lint(tcx, impl_m, impl_m_hir_id, bad_args); - }); - } - CheckImpliedWfMode::Skip => { - if infcx.tainted_by_errors().is_none() { - infcx.err_ctxt().report_region_errors(impl_m_def_id, &errors); - } - return Err(tcx - .sess - .delay_span_bug(rustc_span::DUMMY_SP, "error should have been emitted")); - } - } + return Err(infcx + .tainted_by_errors() + .unwrap_or_else(|| infcx.err_ctxt().report_region_errors(impl_m_def_id, &errors))); } Ok(()) } -fn extract_bad_args_for_implies_lint<'tcx>( - tcx: TyCtxt<'tcx>, - errors: &[infer::RegionResolutionError<'tcx>], - (trait_m, trait_sig): (ty::AssocItem, ty::FnSig<'tcx>), - (impl_m, impl_sig): (ty::AssocItem, ty::FnSig<'tcx>), - hir_id: hir::HirId, -) -> Vec<(Span, Option<String>)> { - let mut blame_generics = vec![]; - for error in errors { - // Look for the subregion origin that contains an input/output type - let origin = match error { - infer::RegionResolutionError::ConcreteFailure(o, ..) => o, - infer::RegionResolutionError::GenericBoundFailure(o, ..) => o, - infer::RegionResolutionError::SubSupConflict(_, _, o, ..) => o, - infer::RegionResolutionError::UpperBoundUniverseConflict(.., o, _) => o, - }; - // Extract (possible) input/output types from origin - match origin { - infer::SubregionOrigin::Subtype(trace) => { - if let Some((a, b)) = trace.values.ty() { - blame_generics.extend([a, b]); - } - } - infer::SubregionOrigin::RelateParamBound(_, ty, _) => blame_generics.push(*ty), - infer::SubregionOrigin::ReferenceOutlivesReferent(ty, _) => blame_generics.push(*ty), - _ => {} - } - } - - let fn_decl = tcx.hir().fn_decl_by_hir_id(hir_id).unwrap(); - let opt_ret_ty = match fn_decl.output { - hir::FnRetTy::DefaultReturn(_) => None, - hir::FnRetTy::Return(ty) => Some(ty), - }; - - // Map late-bound regions from trait to impl, so the names are right. - let mapping = std::iter::zip( - tcx.fn_sig(trait_m.def_id).skip_binder().bound_vars(), - tcx.fn_sig(impl_m.def_id).skip_binder().bound_vars(), - ) - .filter_map(|(impl_bv, trait_bv)| { - if let ty::BoundVariableKind::Region(impl_bv) = impl_bv - && let ty::BoundVariableKind::Region(trait_bv) = trait_bv - { - Some((impl_bv, trait_bv)) - } else { - None - } - }) - .collect(); - - // For each arg, see if it was in the "blame" of any of the region errors. - // If so, then try to produce a suggestion to replace the argument type with - // one from the trait. - let mut bad_args = vec![]; - for (idx, (ty, hir_ty)) in - std::iter::zip(impl_sig.inputs_and_output, fn_decl.inputs.iter().chain(opt_ret_ty)) - .enumerate() - { - let expected_ty = trait_sig.inputs_and_output[idx] - .fold_with(&mut RemapLateBound { tcx, mapping: &mapping }); - if blame_generics.iter().any(|blame| ty.contains(*blame)) { - let expected_ty_sugg = expected_ty.to_string(); - bad_args.push(( - hir_ty.span, - // Only suggest something if it actually changed. - (expected_ty_sugg != ty.to_string()).then_some(expected_ty_sugg), - )); - } - } - - bad_args -} - struct RemapLateBound<'a, 'tcx> { tcx: TyCtxt<'tcx>, mapping: &'a FxHashMap<ty::BoundRegionKind, ty::BoundRegionKind>, @@ -532,8 +401,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> { } fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if let ty::ReFree(fr) = *r { - ty::Region::new_free( + if let ty::ReLateParam(fr) = *r { + ty::Region::new_late_param( self.tcx, fr.scope, self.mapping.get(&fr.bound_region).copied().unwrap_or(fr.bound_region), @@ -544,53 +413,6 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RemapLateBound<'_, 'tcx> { } } -fn emit_implied_wf_lint<'tcx>( - tcx: TyCtxt<'tcx>, - impl_m: ty::AssocItem, - hir_id: hir::HirId, - bad_args: Vec<(Span, Option<String>)>, -) { - let span: MultiSpan = if bad_args.is_empty() { - tcx.def_span(impl_m.def_id).into() - } else { - bad_args.iter().map(|(span, _)| *span).collect::<Vec<_>>().into() - }; - tcx.struct_span_lint_hir( - rustc_session::lint::builtin::IMPLIED_BOUNDS_ENTAILMENT, - hir_id, - span, - "impl method assumes more implied bounds than the corresponding trait method", - |lint| { - let bad_args: Vec<_> = - bad_args.into_iter().filter_map(|(span, sugg)| Some((span, sugg?))).collect(); - if !bad_args.is_empty() { - lint.multipart_suggestion( - format!( - "replace {} type{} to make the impl signature compatible", - pluralize!("this", bad_args.len()), - pluralize!(bad_args.len()) - ), - bad_args, - Applicability::MaybeIncorrect, - ); - } - lint - }, - ); -} - -#[derive(Debug, PartialEq, Eq)] -enum CheckImpliedWfMode { - /// Checks implied well-formedness of the impl method. If it fails, we will - /// re-check with `Skip`, and emit a lint if it succeeds. - Check, - /// Skips checking implied well-formedness of the impl method, but will emit - /// a lint if the `compare_method_predicate_entailment` succeeded. This means that - /// the reason that we had failed earlier during `Check` was due to the impl - /// having stronger requirements than the trait. - Skip, -} - fn compare_asyncness<'tcx>( tcx: TyCtxt<'tcx>, impl_m: ty::AssocItem, @@ -667,7 +489,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let trait_to_impl_args = impl_trait_ref.args; - let impl_m_hir_id = tcx.hir().local_def_id_to_hir_id(impl_m_def_id); + let impl_m_hir_id = tcx.local_def_id_to_hir_id(impl_m_def_id); let return_span = tcx.hir().fn_decl_by_hir_id(impl_m_hir_id).unwrap().output.span(); let cause = ObligationCause::new( return_span, @@ -937,7 +759,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( remapped_types.insert(def_id, ty::EarlyBinder::bind(ty)); } Err(err) => { - let reported = tcx.sess.delay_span_bug( + let reported = tcx.sess.span_delayed_bug( return_span, format!("could not fully resolve: {ty} => {err:?}"), ); @@ -1078,20 +900,26 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> { region: ty::Region<'tcx>, ) -> Result<ty::Region<'tcx>, Self::Error> { match region.kind() { - // Remap all free regions, which correspond to late-bound regions in the function. - ty::ReFree(_) => {} + // Remap late-bound regions from the function. + ty::ReLateParam(_) => {} // Remap early-bound regions as long as they don't come from the `impl` itself, // in which case we don't really need to renumber them. - ty::ReEarlyBound(ebr) if self.tcx.parent(ebr.def_id) != self.impl_def_id => {} + ty::ReEarlyParam(ebr) if self.tcx.parent(ebr.def_id) != self.impl_def_id => {} _ => return Ok(region), } - let e = if let Some(region) = self.map.get(®ion) { - if let ty::ReEarlyBound(e) = region.kind() { e } else { bug!() } + let e = if let Some(id_region) = self.map.get(®ion) { + if let ty::ReEarlyParam(e) = id_region.kind() { + e + } else { + bug!( + "expected to map region {region} to early-bound identity region, but got {id_region}" + ); + } } else { let guar = match region.kind() { - ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. }) - | ty::ReFree(ty::FreeRegion { + ty::ReEarlyParam(ty::EarlyParamRegion { def_id, .. }) + | ty::ReLateParam(ty::LateParamRegion { bound_region: ty::BoundRegionKind::BrNamed(def_id, _), .. }) => { @@ -1114,14 +942,16 @@ impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> { .note(format!("hidden type inferred to be `{}`", self.ty)) .emit() } - _ => self.tcx.sess.delay_span_bug(DUMMY_SP, "should've been able to remap region"), + _ => { + self.tcx.sess.span_delayed_bug(DUMMY_SP, "should've been able to remap region") + } }; return Err(guar); }; - Ok(ty::Region::new_early_bound( + Ok(ty::Region::new_early_param( self.tcx, - ty::EarlyBoundRegion { + ty::EarlyParamRegion { def_id: e.def_id, name: e.name, index: (e.index as usize - self.num_trait_args + self.num_impl_args) as u32, @@ -1140,7 +970,7 @@ fn report_trait_method_mismatch<'tcx>( ) -> ErrorGuaranteed { let tcx = infcx.tcx; let (impl_err_span, trait_err_span) = - extract_spans_for_error_reporting(&infcx, terr, &cause, impl_m, trait_m); + extract_spans_for_error_reporting(infcx, terr, &cause, impl_m, trait_m); let mut diag = struct_span_err!( tcx.sess, @@ -1473,7 +1303,7 @@ fn compare_number_of_generics<'tcx>( // inheriting the generics from will also have mismatched arguments, and // we'll report an error for that instead. Delay a bug for safety, though. if trait_.is_impl_trait_in_trait() { - return Err(tcx.sess.delay_span_bug( + return Err(tcx.sess.span_delayed_bug( rustc_span::DUMMY_SP, "errors comparing numbers of generics of trait/impl functions were not emitted", )); @@ -1708,92 +1538,87 @@ fn compare_synthetic_generics<'tcx>( trait_m.name ); err.span_label(trait_span, "declaration in trait here"); - match (impl_synthetic, trait_synthetic) { + if impl_synthetic { // The case where the impl method uses `impl Trait` but the trait method uses // explicit generics - (true, false) => { - err.span_label(impl_span, "expected generic parameter, found `impl Trait`"); - let _: Option<_> = try { - // try taking the name from the trait impl - // FIXME: this is obviously suboptimal since the name can already be used - // as another generic argument - let new_name = tcx.opt_item_name(trait_def_id)?; - let trait_m = trait_m.def_id.as_local()?; - let trait_m = tcx.hir().expect_trait_item(trait_m); - - let impl_m = impl_m.def_id.as_local()?; - let impl_m = tcx.hir().expect_impl_item(impl_m); - - // in case there are no generics, take the spot between the function name - // and the opening paren of the argument list - let new_generics_span = tcx.def_ident_span(impl_def_id)?.shrink_to_hi(); - // in case there are generics, just replace them - let generics_span = - impl_m.generics.span.substitute_dummy(new_generics_span); - // replace with the generics from the trait - let new_generics = - tcx.sess.source_map().span_to_snippet(trait_m.generics.span).ok()?; - - err.multipart_suggestion( - "try changing the `impl Trait` argument to a generic parameter", - vec![ - // replace `impl Trait` with `T` - (impl_span, new_name.to_string()), - // replace impl method generics with trait method generics - // This isn't quite right, as users might have changed the names - // of the generics, but it works for the common case - (generics_span, new_generics), - ], - Applicability::MaybeIncorrect, - ); - }; - } + err.span_label(impl_span, "expected generic parameter, found `impl Trait`"); + let _: Option<_> = try { + // try taking the name from the trait impl + // FIXME: this is obviously suboptimal since the name can already be used + // as another generic argument + let new_name = tcx.opt_item_name(trait_def_id)?; + let trait_m = trait_m.def_id.as_local()?; + let trait_m = tcx.hir().expect_trait_item(trait_m); + + let impl_m = impl_m.def_id.as_local()?; + let impl_m = tcx.hir().expect_impl_item(impl_m); + + // in case there are no generics, take the spot between the function name + // and the opening paren of the argument list + let new_generics_span = tcx.def_ident_span(impl_def_id)?.shrink_to_hi(); + // in case there are generics, just replace them + let generics_span = impl_m.generics.span.substitute_dummy(new_generics_span); + // replace with the generics from the trait + let new_generics = + tcx.sess.source_map().span_to_snippet(trait_m.generics.span).ok()?; + + err.multipart_suggestion( + "try changing the `impl Trait` argument to a generic parameter", + vec![ + // replace `impl Trait` with `T` + (impl_span, new_name.to_string()), + // replace impl method generics with trait method generics + // This isn't quite right, as users might have changed the names + // of the generics, but it works for the common case + (generics_span, new_generics), + ], + Applicability::MaybeIncorrect, + ); + }; + } else { // The case where the trait method uses `impl Trait`, but the impl method uses // explicit generics. - (false, true) => { - err.span_label(impl_span, "expected `impl Trait`, found generic parameter"); - let _: Option<_> = try { - let impl_m = impl_m.def_id.as_local()?; - let impl_m = tcx.hir().expect_impl_item(impl_m); - let (sig, _) = impl_m.expect_fn(); - let input_tys = sig.decl.inputs; - - struct Visitor(Option<Span>, hir::def_id::LocalDefId); - impl<'v> intravisit::Visitor<'v> for Visitor { - fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { - intravisit::walk_ty(self, ty); - if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind - && let Res::Def(DefKind::TyParam, def_id) = path.res - && def_id == self.1.to_def_id() - { - self.0 = Some(ty.span); - } + err.span_label(impl_span, "expected `impl Trait`, found generic parameter"); + let _: Option<_> = try { + let impl_m = impl_m.def_id.as_local()?; + let impl_m = tcx.hir().expect_impl_item(impl_m); + let (sig, _) = impl_m.expect_fn(); + let input_tys = sig.decl.inputs; + + struct Visitor(Option<Span>, hir::def_id::LocalDefId); + impl<'v> intravisit::Visitor<'v> for Visitor { + fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { + intravisit::walk_ty(self, ty); + if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = ty.kind + && let Res::Def(DefKind::TyParam, def_id) = path.res + && def_id == self.1.to_def_id() + { + self.0 = Some(ty.span); } } + } - let mut visitor = Visitor(None, impl_def_id); - for ty in input_tys { - intravisit::Visitor::visit_ty(&mut visitor, ty); - } - let span = visitor.0?; - - let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds; - let bounds = bounds.first()?.span().to(bounds.last()?.span()); - let bounds = tcx.sess.source_map().span_to_snippet(bounds).ok()?; - - err.multipart_suggestion( - "try removing the generic parameter and using `impl Trait` instead", - vec![ - // delete generic parameters - (impl_m.generics.span, String::new()), - // replace param usage with `impl Trait` - (span, format!("impl {bounds}")), - ], - Applicability::MaybeIncorrect, - ); - }; - } - _ => unreachable!(), + let mut visitor = Visitor(None, impl_def_id); + for ty in input_tys { + intravisit::Visitor::visit_ty(&mut visitor, ty); + } + let span = visitor.0?; + + let bounds = impl_m.generics.bounds_for_param(impl_def_id).next()?.bounds; + let bounds = bounds.first()?.span().to(bounds.last()?.span()); + let bounds = tcx.sess.source_map().span_to_snippet(bounds).ok()?; + + err.multipart_suggestion( + "try removing the generic parameter and using `impl Trait` instead", + vec![ + // delete generic parameters + (impl_m.generics.span, String::new()), + // replace param usage with `impl Trait` + (span, format!("impl {bounds}")), + ], + Applicability::MaybeIncorrect, + ); + }; } error_found = Some(err.emit_unless(delay)); } @@ -1857,7 +1682,9 @@ fn compare_generic_param_kinds<'tcx>( // this is exhaustive so that anyone adding new generic param kinds knows // to make sure this error is reported for them. (Const { .. }, Const { .. }) | (Type { .. }, Type { .. }) => false, - (Lifetime { .. }, _) | (_, Lifetime { .. }) => unreachable!(), + (Lifetime { .. }, _) | (_, Lifetime { .. }) => { + bug!("lifetime params are expected to be filtered by `ty_const_params_of`") + } } { let param_impl_span = tcx.def_span(param_impl.def_id); let param_trait_span = tcx.def_span(param_trait.def_id); @@ -1881,7 +1708,10 @@ fn compare_generic_param_kinds<'tcx>( ) } Type { .. } => format!("{prefix} type parameter"), - Lifetime { .. } => unreachable!(), + Lifetime { .. } => span_bug!( + tcx.def_span(param.def_id), + "lifetime params are expected to be filtered by `ty_const_params_of`" + ), }; let trait_header_span = tcx.def_ident_span(tcx.parent(trait_item.def_id)).unwrap(); @@ -2179,13 +2009,16 @@ pub(super) fn check_type_bounds<'tcx>( let impl_ty_span = if impl_ty.is_impl_trait_in_trait() { tcx.def_span(impl_ty_def_id) } else { - match tcx.hir().get_by_def_id(impl_ty_def_id) { + match tcx.hir_node_by_def_id(impl_ty_def_id) { hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(_, Some(ty)), .. }) => ty.span, hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Type(ty), .. }) => ty.span, - _ => bug!(), + item => span_bug!( + tcx.def_span(impl_ty_def_id), + "cannot call `check_type_bounds` on item: {item:?}", + ), } }; let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl_ty_def_id)?; @@ -2345,7 +2178,7 @@ fn param_env_with_gat_bounds<'tcx>( let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name); let bound_var = ty::BoundVariableKind::Region(kind); bound_vars.push(bound_var); - ty::Region::new_late_bound( + ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index bc5029a1d..67796855e 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -91,7 +91,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( // This opaque also needs to be from the impl method -- otherwise, // it's a refinement to a TAIT. - if !tcx.hir().get_if_local(impl_opaque.def_id).map_or(false, |node| { + if !tcx.hir().get_if_local(impl_opaque.def_id).is_some_and(|node| { matches!( node.expect_item().expect_opaque_ty().origin, hir::OpaqueTyOrigin::AsyncFn(def_id) | hir::OpaqueTyOrigin::FnReturn(def_id) @@ -153,7 +153,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( trait_m_sig.inputs_and_output, )); if !ocx.select_all_or_error().is_empty() { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( DUMMY_SP, "encountered errors when checking RPITIT refinement (selection)", ); @@ -165,7 +165,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( ); let errors = infcx.resolve_regions(&outlives_env); if !errors.is_empty() { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( DUMMY_SP, "encountered errors when checking RPITIT refinement (regions)", ); @@ -173,7 +173,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( } // Resolve any lifetime variables that may have been introduced during normalization. let Ok((trait_bounds, impl_bounds)) = infcx.fully_resolve((trait_bounds, impl_bounds)) else { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( DUMMY_SP, "encountered errors when checking RPITIT refinement (resolution)", ); @@ -262,7 +262,10 @@ fn report_mismatched_rpitit_signature<'tcx>( if tcx.asyncness(impl_m_def_id).is_async() && tcx.asyncness(trait_m_def_id).is_async() { let ty::Alias(ty::Projection, future_ty) = return_ty.kind() else { - bug!(); + span_bug!( + tcx.def_span(trait_m_def_id), + "expected return type of async fn in trait to be a AFIT projection" + ); }; let Some(future_output_ty) = tcx .explicit_item_bounds(future_ty.def_id) @@ -272,13 +275,13 @@ fn report_mismatched_rpitit_signature<'tcx>( _ => None, }) else { - bug!() + span_bug!(tcx.def_span(trait_m_def_id), "expected `Future` projection bound in AFIT"); }; return_ty = future_output_ty; } let (span, impl_return_span, pre, post) = - match tcx.hir().get_by_def_id(impl_m_def_id.expect_local()).fn_decl().unwrap().output { + match tcx.hir_node_by_def_id(impl_m_def_id.expect_local()).fn_decl().unwrap().output { hir::FnRetTy::DefaultReturn(span) => (tcx.def_span(impl_m_def_id), span, "-> ", " "), hir::FnRetTy::Return(ty) => (ty.span, ty.span, "", ""), }; diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index dda3f7425..58c77bb45 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -66,7 +66,7 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro // already checked by coherence, but compilation may // not have been terminated. let span = tcx.def_span(drop_impl_did); - let reported = tcx.sess.delay_span_bug( + let reported = tcx.sess.span_delayed_bug( span, format!("should have been rejected by coherence check: {dtor_self_type}"), ); @@ -81,8 +81,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( self_type_did: DefId, adt_to_impl_args: GenericArgsRef<'tcx>, ) -> Result<(), ErrorGuaranteed> { - let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyEarlyBound) - else { + let Err(arg) = tcx.uses_unique_generic_params(adt_to_impl_args, CheckRegions::OnlyParam) else { return Ok(()); }; diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index 6681292c9..1d737e17e 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -42,8 +42,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { if !def_id.is_local() { return None; } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - match tcx.hir().find(hir_id) { + let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); + match tcx.opt_hir_node(hir_id) { Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => { generics.params.is_empty().not().then_some(generics.span) } @@ -57,8 +57,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { if !def_id.is_local() { return None; } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - match tcx.hir().find(hir_id) { + let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); + match tcx.opt_hir_node(hir_id) { Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })) => { Some(generics.where_clause_span) } @@ -79,8 +79,8 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { if !def_id.is_local() { return None; } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - match tcx.hir().find(hir_id) { + let hir_id = tcx.local_def_id_to_hir_id(def_id.expect_local()); + match tcx.opt_hir_node(hir_id) { Some(Node::Item(hir::Item { kind: hir::ItemKind::Fn(fn_sig, _, _), .. })) => { Some(fn_sig.decl.output.span()) } @@ -92,24 +92,6 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { let mut error = false; let main_diagnostics_def_id = main_fn_diagnostics_def_id(tcx, main_def_id, main_span); - let main_fn_generics = tcx.generics_of(main_def_id); - let main_fn_predicates = tcx.predicates_of(main_def_id); - if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() { - let generics_param_span = main_fn_generics_params_span(tcx, main_def_id); - tcx.sess.emit_err(errors::MainFunctionGenericParameters { - span: generics_param_span.unwrap_or(main_span), - label_span: generics_param_span, - }); - error = true; - } else if !main_fn_predicates.predicates.is_empty() { - // generics may bring in implicit predicates, so we skip this check if generics is present. - let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id); - tcx.sess.emit_err(errors::WhereClauseOnMain { - span: generics_where_clauses_span.unwrap_or(main_span), - generics_span: generics_where_clauses_span, - }); - error = true; - } let main_asyncness = tcx.asyncness(main_def_id); if main_asyncness.is_async() { @@ -142,10 +124,6 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { if let Some(term_did) = tcx.lang_items().termination() { let return_ty = main_fnsig.output(); let return_ty_span = main_fn_return_type_span(tcx, main_def_id).unwrap_or(main_span); - if !return_ty.bound_vars().is_empty() { - tcx.sess.emit_err(errors::MainFunctionReturnTypeGeneric { span: return_ty_span }); - error = true; - } let return_ty = return_ty.skip_binder(); let infcx = tcx.infer_ctxt().build(); let cause = traits::ObligationCause::new( @@ -180,7 +158,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { Abi::Rust, )); - check_function_signature( + if check_function_signature( tcx, ObligationCause::new( main_span, @@ -189,17 +167,38 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { ), main_def_id, expected_sig, - ); + ) + .is_err() + { + return; + } + + let main_fn_generics = tcx.generics_of(main_def_id); + let main_fn_predicates = tcx.predicates_of(main_def_id); + if main_fn_generics.count() != 0 || !main_fnsig.bound_vars().is_empty() { + let generics_param_span = main_fn_generics_params_span(tcx, main_def_id); + tcx.sess.emit_err(errors::MainFunctionGenericParameters { + span: generics_param_span.unwrap_or(main_span), + label_span: generics_param_span, + }); + } else if !main_fn_predicates.predicates.is_empty() { + // generics may bring in implicit predicates, so we skip this check if generics is present. + let generics_where_clauses_span = main_fn_where_clauses_span(tcx, main_def_id); + tcx.sess.emit_err(errors::WhereClauseOnMain { + span: generics_where_clauses_span.unwrap_or(main_span), + generics_span: generics_where_clauses_span, + }); + } } fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { let start_def_id = start_def_id.expect_local(); - let start_id = tcx.hir().local_def_id_to_hir_id(start_def_id); + let start_id = tcx.local_def_id_to_hir_id(start_def_id); let start_span = tcx.def_span(start_def_id); let start_t = tcx.type_of(start_def_id).instantiate_identity(); match start_t.kind() { ty::FnDef(..) => { - if let Some(Node::Item(it)) = tcx.hir().find(start_id) { + if let Some(Node::Item(it)) = tcx.opt_hir_node(start_id) { if let hir::ItemKind::Fn(sig, generics, _) = &it.kind { let mut error = false; if !generics.params.is_empty() { @@ -255,7 +254,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { Abi::Rust, )); - check_function_signature( + let _ = check_function_signature( tcx, ObligationCause::new( start_span, diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index c61719c1f..126bab68a 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -55,7 +55,7 @@ fn equate_intrinsic_type<'tcx>( && gen_count_ok(own_counts.consts, n_cts, "const") { let it_def_id = it.owner_id.def_id; - check_function_signature( + let _ = check_function_signature( tcx, ObligationCause::new(it.span, it_def_id, ObligationCauseCode::IntrinsicType), it_def_id.into(), @@ -143,12 +143,12 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ]); let mk_va_list_ty = |mutbl| { tcx.lang_items().va_list().map(|did| { - let region = ty::Region::new_late_bound( + let region = ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }, ); - let env_region = ty::Region::new_late_bound( + let env_region = ty::Region::new_bound( tcx, ty::INNERMOST, ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv }, @@ -225,25 +225,6 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ], Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }), ), - sym::option_payload_ptr => { - let option_def_id = tcx.require_lang_item(hir::LangItem::Option, None); - let p0 = param(0); - ( - 1, - vec![Ty::new_ptr( - tcx, - ty::TypeAndMut { - ty: Ty::new_adt( - tcx, - tcx.adt_def(option_def_id), - tcx.mk_args_from_iter([ty::GenericArg::from(p0)].into_iter()), - ), - mutbl: hir::Mutability::Not, - }, - )], - Ty::new_ptr(tcx, ty::TypeAndMut { ty: p0, mutbl: hir::Mutability::Not }), - ) - } sym::ptr_mask => ( 1, vec![ @@ -411,7 +392,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { 1, vec![Ty::new_imm_ref( tcx, - ty::Region::new_late_bound(tcx, ty::INNERMOST, br), + ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0), )], Ty::new_projection(tcx, discriminant_def_id, tcx.mk_args(&[param(0).into()])), @@ -465,11 +446,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { sym::raw_eq => { let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon }; - let param_ty = Ty::new_imm_ref( - tcx, - ty::Region::new_late_bound(tcx, ty::INNERMOST, br), - param(0), - ); + let param_ty = + Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0)); (1, vec![param_ty; 2], tcx.types.bool) } @@ -543,6 +521,8 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) sym::simd_fpowi => (1, 0, vec![param(0), tcx.types.i32], param(0)), sym::simd_fma => (1, 0, vec![param(0), param(0), param(0)], param(0)), sym::simd_gather => (3, 0, vec![param(0), param(1), param(2)], param(0)), + sym::simd_masked_load => (3, 0, vec![param(0), param(1), param(2)], param(2)), + sym::simd_masked_store => (3, 0, vec![param(0), param(1), param(2)], Ty::new_unit(tcx)), sym::simd_scatter => (3, 0, vec![param(0), param(1), param(2)], Ty::new_unit(tcx)), sym::simd_insert => (2, 0, vec![param(0), tcx.types.u32, param(1)], param(0)), sym::simd_extract => (2, 0, vec![param(0), tcx.types.u32], param(1)), diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs index cd7e99172..d86ebc2c9 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs @@ -49,7 +49,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { 16 => InlineAsmType::I16, 32 => InlineAsmType::I32, 64 => InlineAsmType::I64, - _ => unreachable!(), + width => bug!("unsupported pointer width: {width}"), }; match *ty.kind() { @@ -101,7 +101,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { 16 => InlineAsmType::VecI16(size), 32 => InlineAsmType::VecI32(size), 64 => InlineAsmType::VecI64(size), - _ => unreachable!(), + width => bug!("unsupported pointer width: {width}"), }) } ty::Float(FloatTy::F32) => Some(InlineAsmType::VecF32(size)), @@ -109,7 +109,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { _ => None, } } - ty::Infer(_) => unreachable!(), + ty::Infer(_) => bug!("unexpected infer ty in asm operand"), _ => None, } } @@ -136,8 +136,15 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { ty::Adt(adt, args) if Some(adt.did()) == self.tcx.lang_items().maybe_uninit() => { let fields = &adt.non_enum_variant().fields; let ty = fields[FieldIdx::from_u32(1)].ty(self.tcx, args); - let ty::Adt(ty, args) = ty.kind() else { unreachable!() }; - assert!(ty.is_manually_drop()); + // FIXME: Are we just trying to map to the `T` in `MaybeUninit<T>`? + // If so, just get it from the args. + let ty::Adt(ty, args) = ty.kind() else { + unreachable!("expected first field of `MaybeUninit` to be an ADT") + }; + assert!( + ty.is_manually_drop(), + "expected first field of `MaybeUnit` to be `ManuallyDrop`" + ); let fields = &ty.non_enum_variant().fields; let ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, args); self.get_asm_ty(ty) @@ -269,7 +276,6 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { lint.help(format!( "or use `{{{idx}:{default_modifier}}}` to keep the default formatting of `{default_result}`", )); - lint }, ); } @@ -281,7 +287,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { pub fn check_asm(&self, asm: &hir::InlineAsm<'tcx>, enclosing_id: LocalDefId) { let target_features = self.tcx.asm_target_features(enclosing_id.to_def_id()); let Some(asm_arch) = self.tcx.sess.asm_arch else { - self.tcx.sess.delay_span_bug(DUMMY_SP, "target architecture does not support asm"); + self.tcx.sess.span_delayed_bug(DUMMY_SP, "target architecture does not support asm"); return; }; for (idx, (op, op_sp)) in asm.operands.iter().enumerate() { @@ -307,7 +313,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if let Err(msg) = reg.validate( asm_arch, self.tcx.sess.relocation_model(), - &target_features, + target_features, &self.tcx.sess.target, op.is_clobber(), ) { @@ -382,7 +388,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { asm.template, true, None, - &target_features, + target_features, ); } hir::InlineAsmOperand::Out { reg, late: _, expr } => { @@ -394,7 +400,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { asm.template, false, None, - &target_features, + target_features, ); } } @@ -406,7 +412,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { asm.template, false, None, - &target_features, + target_features, ); } hir::InlineAsmOperand::SplitInOut { reg, late: _, in_expr, out_expr } => { @@ -417,7 +423,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { asm.template, true, None, - &target_features, + target_features, ); if let Some(out_expr) = out_expr { self.check_asm_operand_type( @@ -427,7 +433,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { asm.template, false, Some((in_expr, in_ty)), - &target_features, + target_features, ); } } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 15c5558fc..e4904a043 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -77,6 +77,7 @@ use std::num::NonZeroU32; use check::check_mod_item_types; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_errors::ErrorGuaranteed; use rustc_errors::{pluralize, struct_span_err, Diagnostic, DiagnosticBuilder}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; @@ -128,9 +129,9 @@ fn get_owner_return_paths( tcx: TyCtxt<'_>, def_id: LocalDefId, ) -> Option<(LocalDefId, ReturnsVisitor<'_>)> { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let parent_id = tcx.hir().get_parent_item(hir_id).def_id; - tcx.hir().find_by_def_id(parent_id).and_then(|node| node.body_id()).map(|body_id| { + tcx.opt_hir_node_by_def_id(parent_id).and_then(|node| node.body_id()).map(|body_id| { let body = tcx.hir().body(body_id); let mut visitor = ReturnsVisitor::default(); visitor.visit_body(body); @@ -141,7 +142,7 @@ fn get_owner_return_paths( /// Forbid defining intrinsics in Rust code, /// as they must always be defined by the compiler. // FIXME: Move this to a more appropriate place. -pub fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) { +pub fn forbid_intrinsic_abi(tcx: TyCtxt<'_>, sp: Span, abi: Abi) { if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = abi { tcx.sess.span_err(sp, "intrinsic must be in `extern \"rust-intrinsic\" { ... }` block"); } @@ -570,7 +571,26 @@ pub fn check_function_signature<'tcx>( mut cause: ObligationCause<'tcx>, fn_id: DefId, expected_sig: ty::PolyFnSig<'tcx>, -) { +) -> Result<(), ErrorGuaranteed> { + fn extract_span_for_error_reporting<'tcx>( + tcx: TyCtxt<'tcx>, + err: TypeError<'_>, + cause: &ObligationCause<'tcx>, + fn_id: LocalDefId, + ) -> rustc_span::Span { + let mut args = { + let node = tcx.hir().expect_owner(fn_id); + let decl = node.fn_decl().unwrap_or_else(|| bug!("expected fn decl, found {:?}", node)); + decl.inputs.iter().map(|t| t.span).chain(std::iter::once(decl.output.span())) + }; + + match err { + TypeError::ArgumentMutability(i) + | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => args.nth(i).unwrap(), + _ => cause.span(), + } + } + let local_id = fn_id.as_local().unwrap_or(CRATE_DEF_ID); let param_env = ty::ParamEnv::empty(); @@ -587,8 +607,7 @@ pub fn check_function_signature<'tcx>( Ok(()) => { let errors = ocx.select_all_or_error(); if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(errors); - return; + return Err(infcx.err_ctxt().report_fulfillment_errors(errors)); } } Err(err) => { @@ -610,30 +629,14 @@ pub fn check_function_signature<'tcx>( false, false, ); - diag.emit(); - return; + return Err(diag.emit()); } } let outlives_env = OutlivesEnvironment::new(param_env); - let _ = ocx.resolve_regions_and_report_errors(local_id, &outlives_env); - - fn extract_span_for_error_reporting<'tcx>( - tcx: TyCtxt<'tcx>, - err: TypeError<'_>, - cause: &ObligationCause<'tcx>, - fn_id: LocalDefId, - ) -> rustc_span::Span { - let mut args = { - let node = tcx.hir().expect_owner(fn_id); - let decl = node.fn_decl().unwrap_or_else(|| bug!("expected fn decl, found {:?}", node)); - decl.inputs.iter().map(|t| t.span).chain(std::iter::once(decl.output.span())) - }; - - match err { - TypeError::ArgumentMutability(i) - | TypeError::ArgumentSorts(ExpectedFound { .. }, i) => args.nth(i).unwrap(), - _ => cause.span(), - } + if let Err(e) = ocx.resolve_regions_and_report_errors(local_id, &outlives_env) { + return Err(e); } + + Ok(()) } diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 40b33117f..37b308f9f 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -414,11 +414,11 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h // then we'll assign too low a count to any `yield` expressions // we encounter in 'right_expression' - they should really occur after all of the // expressions in 'left_expression'. - visitor.visit_expr(&right_expr); + visitor.visit_expr(right_expr); visitor.pessimistic_yield = prev_pessimistic; debug!("resolve_expr - restoring pessimistic_yield to {}", prev_pessimistic); - visitor.visit_expr(&left_expr); + visitor.visit_expr(left_expr); debug!("resolve_expr - fixing up counts to {}", visitor.expr_and_pat_count); // Remove and process any scopes pushed by the visitor @@ -582,7 +582,7 @@ fn resolve_local<'tcx>( // due to rule C. if let Some(expr) = init { - record_rvalue_scope_if_borrow_expr(visitor, &expr, blk_scope); + record_rvalue_scope_if_borrow_expr(visitor, expr, blk_scope); if let Some(pat) = pat { if is_binding_pat(pat) { @@ -645,25 +645,24 @@ fn resolve_local<'tcx>( match pat.kind { PatKind::Binding(hir::BindingAnnotation(hir::ByRef::Yes, _), ..) => true, - PatKind::Struct(_, field_pats, _) => { - field_pats.iter().any(|fp| is_binding_pat(&fp.pat)) - } + PatKind::Struct(_, field_pats, _) => field_pats.iter().any(|fp| is_binding_pat(fp.pat)), PatKind::Slice(pats1, pats2, pats3) => { - pats1.iter().any(|p| is_binding_pat(&p)) - || pats2.iter().any(|p| is_binding_pat(&p)) - || pats3.iter().any(|p| is_binding_pat(&p)) + pats1.iter().any(|p| is_binding_pat(p)) + || pats2.iter().any(|p| is_binding_pat(p)) + || pats3.iter().any(|p| is_binding_pat(p)) } PatKind::Or(subpats) | PatKind::TupleStruct(_, subpats, _) - | PatKind::Tuple(subpats, _) => subpats.iter().any(|p| is_binding_pat(&p)), + | PatKind::Tuple(subpats, _) => subpats.iter().any(|p| is_binding_pat(p)), - PatKind::Box(subpat) => is_binding_pat(&subpat), + PatKind::Box(subpat) => is_binding_pat(subpat), PatKind::Ref(_, _) | PatKind::Binding(hir::BindingAnnotation(hir::ByRef::No, _), ..) | PatKind::Wild + | PatKind::Never | PatKind::Path(_) | PatKind::Lit(_) | PatKind::Range(_, _, _) => false, @@ -700,20 +699,20 @@ fn resolve_local<'tcx>( } hir::ExprKind::Struct(_, fields, _) => { for field in fields { - record_rvalue_scope_if_borrow_expr(visitor, &field.expr, blk_id); + record_rvalue_scope_if_borrow_expr(visitor, field.expr, blk_id); } } hir::ExprKind::Array(subexprs) | hir::ExprKind::Tup(subexprs) => { for subexpr in subexprs { - record_rvalue_scope_if_borrow_expr(visitor, &subexpr, blk_id); + record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id); } } hir::ExprKind::Cast(subexpr, _) => { - record_rvalue_scope_if_borrow_expr(visitor, &subexpr, blk_id) + record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id) } hir::ExprKind::Block(block, _) => { if let Some(subexpr) = block.expr { - record_rvalue_scope_if_borrow_expr(visitor, &subexpr, blk_id); + record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id); } } hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) => { @@ -795,13 +794,13 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { // The arguments and `self` are parented to the fn. self.cx.var_parent = self.cx.parent.take(); for param in body.params { - self.visit_pat(¶m.pat); + self.visit_pat(param.pat); } // The body of the every fn is a root scope. self.cx.parent = self.cx.var_parent; if self.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() { - self.visit_expr(&body.value) + self.visit_expr(body.value) } else { // Only functions have an outer terminating (drop) scope, while // temporaries in constant initializers may be 'static, but only @@ -822,7 +821,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { // (i.e., `'static`), which means that after `g` returns, it drops, // and all the associated destruction scope rules apply. self.cx.var_parent = None; - resolve_local(self, None, Some(&body.value)); + resolve_local(self, None, Some(body.value)); } if body.coroutine_kind.is_some() { @@ -849,7 +848,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { resolve_expr(self, ex); } fn visit_local(&mut self, l: &'tcx Local<'tcx>) { - resolve_local(self, Some(&l.pat), l.init) + resolve_local(self, Some(l.pat), l.init) } } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index eb4491b89..b2ff79591 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -118,10 +118,10 @@ where if tcx.sess.err_count() > 0 { return Err(err); } else { - // HACK(oli-obk): tests/ui/specialization/min_specialization/specialize_on_type_error.rs causes an - // error (delay_span_bug) during normalization, without reporting an error, so we need to act as if - // no error happened, in order to let our callers continue and report an error later in - // check_impl_items_against_trait. + // HACK(oli-obk): tests/ui/specialization/min_specialization/specialize_on_type_error.rs + // causes an error (span_delayed_bug) during normalization, without reporting an error, + // so we need to act as if no error happened, in order to let our callers continue and + // report an error later in check_impl_items_against_trait. return Ok(()); } } @@ -204,11 +204,14 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() res = Err(err.emit()); } // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span. - match (tcx.impl_polarity(def_id), impl_.polarity) { - (ty::ImplPolarity::Positive, _) => { + match tcx.impl_polarity(def_id) { + ty::ImplPolarity::Positive => { res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait)); } - (ty::ImplPolarity::Negative, ast::ImplPolarity::Negative(span)) => { + ty::ImplPolarity::Negative => { + let ast::ImplPolarity::Negative(span) = impl_.polarity else { + bug!("impl_polarity query disagrees with impl's polarity in AST"); + }; // FIXME(#27579): what amount of WF checking do we need for neg impls? if let hir::Defaultness::Default { .. } = impl_.defaultness { let mut spans = vec![span]; @@ -222,10 +225,9 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() .emit()); } } - (ty::ImplPolarity::Reservation, _) => { + ty::ImplPolarity::Reservation => { // FIXME: what amount of WF checking do we need for reservation impls? } - _ => unreachable!(), } res } @@ -584,7 +586,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( // reflected in a where clause on the GAT itself. for (ty, ty_idx) in &types { // In our example, requires that `Self: 'a` - if ty_known_to_outlive(tcx, item_def_id, param_env, &wf_tys, *ty, *region_a) { + if ty_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *ty, *region_a) { debug!(?ty_idx, ?region_a_idx); debug!("required clause: {ty} must outlive {region_a}"); // Translate into the generic parameters of the GAT. In @@ -595,9 +597,9 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( // Same for the region. In our example, 'a corresponds // to the 'me parameter. let region_param = gat_generics.param_at(*region_a_idx, tcx); - let region_param = ty::Region::new_early_bound( + let region_param = ty::Region::new_early_param( tcx, - ty::EarlyBoundRegion { + ty::EarlyParamRegion { def_id: region_param.def_id, index: region_param.index, name: region_param.name, @@ -623,14 +625,14 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( if matches!(**region_b, ty::ReStatic | ty::ReError(_)) || region_a == region_b { continue; } - if region_known_to_outlive(tcx, item_def_id, param_env, &wf_tys, *region_a, *region_b) { + if region_known_to_outlive(tcx, item_def_id, param_env, wf_tys, *region_a, *region_b) { debug!(?region_a_idx, ?region_b_idx); debug!("required clause: {region_a} must outlive {region_b}"); // Translate into the generic parameters of the GAT. let region_a_param = gat_generics.param_at(*region_a_idx, tcx); - let region_a_param = ty::Region::new_early_bound( + let region_a_param = ty::Region::new_early_param( tcx, - ty::EarlyBoundRegion { + ty::EarlyParamRegion { def_id: region_a_param.def_id, index: region_a_param.index, name: region_a_param.name, @@ -638,9 +640,9 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>( ); // Same for the region. let region_b_param = gat_generics.param_at(*region_b_idx, tcx); - let region_b_param = ty::Region::new_early_bound( + let region_b_param = ty::Region::new_early_param( tcx, - ty::EarlyBoundRegion { + ty::EarlyParamRegion { def_id: region_b_param.def_id, index: region_b_param.index, name: region_b_param.name, @@ -671,7 +673,7 @@ fn ty_known_to_outlive<'tcx>( ty: Ty<'tcx>, region: ty::Region<'tcx>, ) -> bool { - resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |infcx, region_bound_pairs| { + resolve_regions_with_wf_tys(tcx, id, param_env, wf_tys, |infcx, region_bound_pairs| { let origin = infer::RelateParamBound(DUMMY_SP, ty, None); let outlives = &mut TypeOutlives::new(infcx, tcx, region_bound_pairs, None, param_env); outlives.type_must_outlive(origin, ty, region, ConstraintCategory::BoringNoLocation); @@ -688,7 +690,7 @@ fn region_known_to_outlive<'tcx>( region_a: ty::Region<'tcx>, region_b: ty::Region<'tcx>, ) -> bool { - resolve_regions_with_wf_tys(tcx, id, param_env, &wf_tys, |mut infcx, _| { + resolve_regions_with_wf_tys(tcx, id, param_env, wf_tys, |mut infcx, _| { use rustc_infer::infer::outlives::obligations::TypeOutlivesDelegate; let origin = infer::RelateRegionParamBound(DUMMY_SP); // `region_a: region_b` -> `region_b <= region_a` @@ -763,7 +765,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GATSubstCollector<'tcx> { ty::Alias(ty::Projection, p) if p.def_id == self.gat => { for (idx, subst) in p.args.iter().enumerate() { match subst.unpack() { - GenericArgKind::Lifetime(lt) if !lt.is_late_bound() => { + GenericArgKind::Lifetime(lt) if !lt.is_bound() => { self.regions.insert((lt, idx)); } GenericArgKind::Type(t) => { @@ -793,7 +795,7 @@ fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool { /// When this is done, suggest using `Self` instead. fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem<'_>) { let (trait_name, trait_def_id) = - match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(item.hir_id()).def_id) { + match tcx.hir_node_by_def_id(tcx.hir().get_parent_item(item.hir_id()).def_id) { hir::Node::Item(item) => match item.kind { hir::ItemKind::Trait(..) => (item.ident, item.owner_id), _ => return, @@ -859,7 +861,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(), hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => Ok(()), // Const parameters are well formed if their type is structural match. - hir::GenericParamKind::Const { ty: hir_ty, default: _ } => { + hir::GenericParamKind::Const { ty: hir_ty, default: _, is_host_effect: _ } => { let ty = tcx.type_of(param.def_id).instantiate_identity(); if tcx.features().adt_const_params { @@ -992,15 +994,6 @@ fn check_associated_item( }) } -fn item_adt_kind(kind: &ItemKind<'_>) -> Option<AdtKind> { - match kind { - ItemKind::Struct(..) => Some(AdtKind::Struct), - ItemKind::Union(..) => Some(AdtKind::Union), - ItemKind::Enum(..) => Some(AdtKind::Enum), - _ => None, - } -} - /// In a type definition, we check that to ensure that the types of the fields are well-formed. fn check_type_defn<'tcx>( tcx: TyCtxt<'tcx>, @@ -1019,7 +1012,7 @@ fn check_type_defn<'tcx>( for field in &variant.fields { let field_id = field.did.expect_local(); let hir::FieldDef { ty: hir_ty, .. } = - tcx.hir().get_by_def_id(field_id).expect_field(); + tcx.hir_node_by_def_id(field_id).expect_field(); let ty = wfcx.normalize( hir_ty.span, None, @@ -1040,7 +1033,7 @@ fn check_type_defn<'tcx>( let ty = tcx.erase_regions(ty); if ty.has_infer() { tcx.sess - .delay_span_bug(item.span, format!("inference variables in {ty:?}")); + .span_delayed_bug(item.span, format!("inference variables in {ty:?}")); // Just treat unresolved type expression as if it needs drop. true } else { @@ -1057,7 +1050,7 @@ fn check_type_defn<'tcx>( let last = idx == variant.fields.len() - 1; let field_id = field.did.expect_local(); let hir::FieldDef { ty: hir_ty, .. } = - tcx.hir().get_by_def_id(field_id).expect_field(); + tcx.hir_node_by_def_id(field_id).expect_field(); let ty = wfcx.normalize( hir_ty.span, None, @@ -1068,9 +1061,14 @@ fn check_type_defn<'tcx>( hir_ty.span, wfcx.body_def_id, traits::FieldSized { - adt_kind: match item_adt_kind(&item.kind) { - Some(i) => i, - None => bug!(), + adt_kind: match &item.kind { + ItemKind::Struct(..) => AdtKind::Struct, + ItemKind::Union(..) => AdtKind::Union, + ItemKind::Enum(..) => AdtKind::Enum, + kind => span_bug!( + item.span, + "should be wfchecking an ADT, got {kind:?}" + ), }, span: hir_ty.span, last, @@ -1302,7 +1300,9 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id | GenericParamDefKind::Const { has_default, .. } => { has_default && def.index >= generics.parent_count as u32 } - GenericParamDefKind::Lifetime => unreachable!(), + GenericParamDefKind::Lifetime => { + span_bug!(tcx.def_span(def.def_id), "lifetime params can have no default") + } }; // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`. @@ -1607,15 +1607,10 @@ fn check_method_receiver<'tcx>( } fn e0307(tcx: TyCtxt<'_>, span: Span, receiver_ty: Ty<'_>) -> ErrorGuaranteed { - struct_span_err!( - tcx.sess.diagnostic(), - span, - E0307, - "invalid `self` parameter type: {receiver_ty}" - ) - .note("type of `self` must be `Self` or a type that dereferences to it") - .help(HELP_FOR_SELF_TYPE) - .emit() + struct_span_err!(tcx.sess.dcx(), span, E0307, "invalid `self` parameter type: {receiver_ty}") + .note("type of `self` must be `Self` or a type that dereferences to it") + .help(HELP_FOR_SELF_TYPE) + .emit() } /// Returns whether `receiver_ty` would be considered a valid receiver type for `self_ty`. If @@ -1750,15 +1745,15 @@ fn check_variances_for_type_defn<'tcx>( } } ItemKind::TyAlias(..) => { - if tcx.type_alias_is_lazy(item.owner_id) { - if tcx.type_of(item.owner_id).skip_binder().references_error() { - return; - } - } else { - bug!(); + assert!( + tcx.type_alias_is_lazy(item.owner_id), + "should not be computing variance of non-weak type alias" + ); + if tcx.type_of(item.owner_id).skip_binder().references_error() { + return; } } - _ => bug!(), + kind => span_bug!(item.span, "cannot compute the variances of {kind:?}"), } let ty_predicates = tcx.predicates_of(item.owner_id); @@ -1812,8 +1807,10 @@ fn check_variances_for_type_defn<'tcx>( // // if they aren't in the same order, then the user has written invalid code, and already // got an error about it (or I'm wrong about this) - tcx.sess - .delay_span_bug(hir_param.span, "hir generics and ty generics in different order"); + tcx.sess.span_delayed_bug( + hir_param.span, + "hir generics and ty generics in different order", + ); continue; } @@ -1880,7 +1877,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { // Match the existing behavior. if pred.is_global() && !pred.has_type_flags(TypeFlags::HAS_BINDER_VARS) { let pred = self.normalize(span, None, pred); - let hir_node = tcx.hir().find_by_def_id(self.body_def_id); + let hir_node = tcx.opt_hir_node_by_def_id(self.body_def_id); // only use the span of the predicate clause (#90869) diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index 9ad73eeff..36cb8f7a2 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -45,7 +45,7 @@ fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) { item.hir_id(), path.span, msg, - |lint| lint, + |_| {}, ); } } diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index e5e192e00..f277badf2 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -550,7 +550,7 @@ fn infringing_fields_error( .entry((ty.clone(), predicate.clone())) .or_default() .push(origin.span()); - if let ty::RegionKind::ReEarlyBound(ebr) = *b + if let ty::RegionKind::ReEarlyParam(ebr) = *b && ebr.has_name() { bounds.push((b.to_string(), a.to_string(), None)); diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 7205b7a21..3f8c0db87 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -198,7 +198,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { // entire graph when there are many connected regions. rustc_index::newtype_index! { - #[custom_encodable] + #[orderable] pub struct RegionId {} } diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 7eeb78374..d33cfe4ad 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -58,7 +58,7 @@ fn do_orphan_check_impl<'tcx>( tr.path.span, trait_ref, impl_.self_ty.span, - &impl_.generics, + impl_.generics, err, )? } @@ -452,7 +452,13 @@ fn lint_auto_trait_impl<'tcx>( trait_ref: ty::TraitRef<'tcx>, impl_def_id: LocalDefId, ) { - assert_eq!(trait_ref.args.len(), 1); + if trait_ref.args.len() != 1 { + tcx.sess.dcx().span_delayed_bug( + tcx.def_span(impl_def_id), + "auto traits cannot have generic parameters", + ); + return; + } let self_ty = trait_ref.self_ty(); let (self_type_did, args) = match self_ty.kind() { ty::Adt(def, args) => (def.did(), args), @@ -491,7 +497,7 @@ fn lint_auto_trait_impl<'tcx>( tcx.struct_span_lint_hir( lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS, - tcx.hir().local_def_id_to_hir_id(impl_def_id), + tcx.local_def_id_to_hir_id(impl_def_id), tcx.def_span(impl_def_id), DelayDm(|| { format!( @@ -516,7 +522,7 @@ fn lint_auto_trait_impl<'tcx>( format!( "try using the same sequence of generic parameters as the {self_descr} definition", ), - ) + ); }, ); } diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 6b18b0ebe..8a02bab92 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -23,7 +23,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { tcx.def_span(def_id), E0199, "implementing the trait `{}` is not unsafe", - trait_ref.print_only_trait_path() + trait_ref.print_trait_sugared() ) .span_suggestion_verbose( item.span.with_hi(item.span.lo() + rustc_span::BytePos(7)), @@ -40,13 +40,13 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { tcx.def_span(def_id), E0200, "the trait `{}` requires an `unsafe impl` declaration", - trait_ref.print_only_trait_path() + trait_ref.print_trait_sugared() ) .note(format!( "the trait `{}` enforces invariants that the compiler can't check. \ Review the trait documentation and make sure this implementation \ upholds those invariants before adding the `unsafe` keyword", - trait_ref.print_only_trait_path() + trait_ref.print_trait_sugared() )) .span_suggestion_verbose( item.span.shrink_to_lo(), @@ -69,7 +69,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { "the trait `{}` enforces invariants that the compiler can't check. \ Review the trait documentation and make sure this implementation \ upholds those invariants before adding the `unsafe` keyword", - trait_ref.print_only_trait_path() + trait_ref.print_trait_sugared() )) .span_suggestion_verbose( item.span.shrink_to_lo(), @@ -82,7 +82,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => { // Reported in AST validation - tcx.sess.delay_span_bug(item.span, "unsafe negative impl"); + tcx.sess.span_delayed_bug(item.span, "unsafe negative impl"); } (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_)) | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 9636c6144..d48535c82 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -221,7 +221,7 @@ pub(crate) fn placeholder_type_error_diag<'tcx>( // Check if parent is const or static let parent_id = tcx.hir().parent_id(hir_ty.hir_id); - let parent_node = tcx.hir().get(parent_id); + let parent_node = tcx.hir_node(parent_id); is_const_or_static = matches!( parent_node, @@ -350,11 +350,11 @@ impl<'tcx> ItemCtxt<'tcx> { } pub fn hir_id(&self) -> hir::HirId { - self.tcx.hir().local_def_id_to_hir_id(self.item_def_id) + self.tcx.local_def_id_to_hir_id(self.item_def_id) } pub fn node(&self) -> hir::Node<'tcx> { - self.tcx.hir().get(self.hir_id()) + self.tcx.hir_node(self.hir_id()) } } @@ -440,10 +440,10 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { second: format!( "{}::", // Replace the existing lifetimes with a new named lifetime. - self.tcx.replace_late_bound_regions_uncached( + self.tcx.instantiate_bound_regions_uncached( poly_trait_ref, |_| { - ty::Region::new_early_bound(self.tcx, ty::EarlyBoundRegion { + ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion { def_id: item_def_id, index: 0, name: Symbol::intern(<_name), @@ -672,7 +672,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) { hir::TraitItemKind::Const(ty, body_id) => { tcx.ensure().type_of(def_id); - if !tcx.sess.diagnostic().has_stashed_diagnostic(ty.span, StashKey::ItemNoType) + if !tcx.sess.dcx().has_stashed_diagnostic(ty.span, StashKey::ItemNoType) && !(is_suggestable_infer_ty(ty) && body_id.is_some()) { // Account for `const C: _;`. @@ -814,7 +814,7 @@ fn convert_variant( }) .collect(); let recovered = match def { - hir::VariantData::Struct(_, r) => *r, + hir::VariantData::Struct { recovered, .. } => *recovered, _ => false, }; ty::VariantDef::new( @@ -835,9 +835,8 @@ fn convert_variant( fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { use rustc_hir::*; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let Node::Item(item) = tcx.hir().get(hir_id) else { - bug!(); + let Node::Item(item) = tcx.hir_node_by_def_id(def_id) else { + bug!("expected ADT to be an item"); }; let repr = tcx.repr_options_of_def(def_id.to_def_id()); @@ -888,7 +887,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> { (adt_kind, variants) } - _ => bug!(), + _ => bug!("{:?} is not an ADT", item.owner_id.def_id), }; tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr) } @@ -1090,7 +1089,7 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { pub fn get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> { if let hir::FnRetTy::Return(ty) = output { if is_suggestable_infer_ty(ty) { - return Some(&*ty); + return Some(*ty); } } None @@ -1101,11 +1100,11 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig< use rustc_hir::Node::*; use rustc_hir::*; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let icx = ItemCtxt::new(tcx, def_id); - let output = match tcx.hir().get(hir_id) { + let output = match tcx.hir_node(hir_id) { TraitItem(hir::TraitItem { kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)), generics, @@ -1186,7 +1185,7 @@ fn infer_return_ty_for_fn_sig<'tcx>( def_id: LocalDefId, icx: &ItemCtxt<'tcx>, ) -> ty::PolyFnSig<'tcx> { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); match get_infer_ret_ty(&sig.decl.output) { Some(ty) => { @@ -1373,7 +1372,7 @@ fn impl_trait_ref( if let Some(ErrorGuaranteed { .. }) = check_impl_constness( tcx, tcx.is_const_trait_impl_raw(def_id.to_def_id()), - &ast_trait_ref, + ast_trait_ref, ) { // we have a const impl, but for a trait without `#[const_trait]`, so // without the host param. If we continue with the HIR trait ref, we get @@ -1383,7 +1382,7 @@ fn impl_trait_ref( let last_segment = path_segments.len() - 1; let mut args = *path_segments[last_segment].args(); let last_arg = args.args.len() - 1; - assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if tcx.has_attr(anon_const.value.def_id, sym::rustc_host))); + assert!(matches!(args.args[last_arg], hir::GenericArg::Const(anon_const) if anon_const.is_desugared_from_effects)); args.args = &args.args[..args.args.len() - 1]; path_segments[last_segment].args = Some(&args); let path = hir::Path { @@ -1394,7 +1393,7 @@ fn impl_trait_ref( let trait_ref = hir::TraitRef { path: &path, hir_ref_id: ast_trait_ref.hir_ref_id }; icx.astconv().instantiate_mono_trait_ref(&trait_ref, selfty) } else { - icx.astconv().instantiate_mono_trait_ref(&ast_trait_ref, selfty) + icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty) } }) .map(ty::EarlyBinder::bind) @@ -1519,7 +1518,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( } else { hir::Unsafety::Unsafe }; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let fty = ItemCtxt::new(tcx, def_id).astconv().ty_of_fn(hir_id, unsafety, abi, decl, None, None); @@ -1551,7 +1550,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( } fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineKind> { - match tcx.hir().get_by_def_id(def_id) { + match tcx.hir_node_by_def_id(def_id) { Node::Expr(&rustc_hir::Expr { kind: rustc_hir::ExprKind::Closure(&rustc_hir::Closure { body, .. }), .. @@ -1561,7 +1560,7 @@ fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineK } fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { - match tcx.hir().get_by_def_id(def_id) { + match tcx.hir_node_by_def_id(def_id) { Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. }) => { matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. }) } diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 3d60c57b9..3ee2822ed 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -9,14 +9,14 @@ use rustc_hir::def_id::LocalDefId; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint; use rustc_span::symbol::{kw, Symbol}; -use rustc_span::{sym, Span}; +use rustc_span::Span; pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { use rustc_hir::*; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); - let node = tcx.hir().get(hir_id); + let node = tcx.hir_node(hir_id); let parent_def_id = match node { Node::ImplItem(_) | Node::TraitItem(_) @@ -182,7 +182,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { } let no_generics = hir::Generics::empty(); - let ast_generics = node.generics().unwrap_or(&no_generics); + let ast_generics = node.generics().unwrap_or(no_generics); let (opt_self, allow_defaults) = match node { Node::Item(item) => { match item.kind { @@ -279,7 +279,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { param.hir_id, param.span, TYPE_DEFAULT_NOT_ALLOWED, - |lint| lint, + |_| {}, ); } Defaults::Deny => { @@ -298,13 +298,11 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { kind, }) } - GenericParamKind::Const { default, .. } => { - let is_host_param = tcx.has_attr(param.def_id, sym::rustc_host); - + GenericParamKind::Const { ty: _, default, is_host_effect } => { if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() - // `rustc_host` effect params are allowed to have defaults. - && !is_host_param + // `host` effect params are allowed to have defaults. + && !is_host_effect { tcx.sess.span_err( param.span, @@ -315,7 +313,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { let index = next_index(); - if is_host_param { + if is_host_effect { if let Some(idx) = host_effect_index { bug!("parent also has host effect param? index: {idx}, def: {def_id:?}"); } @@ -330,7 +328,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { pure_wrt_drop: param.pure_wrt_drop, kind: ty::GenericParamDefKind::Const { has_default: default.is_some(), - is_host_effect: is_host_param, + is_host_effect, }, }) } @@ -458,11 +456,11 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S match node { Node::TraitItem(item) => match &item.kind { - hir::TraitItemKind::Fn(sig, _) => has_late_bound_regions(tcx, &item.generics, sig.decl), + hir::TraitItemKind::Fn(sig, _) => has_late_bound_regions(tcx, item.generics, sig.decl), _ => None, }, Node::ImplItem(item) => match &item.kind { - hir::ImplItemKind::Fn(sig, _) => has_late_bound_regions(tcx, &item.generics, sig.decl), + hir::ImplItemKind::Fn(sig, _) => has_late_bound_regions(tcx, item.generics, sig.decl), _ => None, }, Node::ForeignItem(item) => match item.kind { @@ -489,7 +487,7 @@ struct AnonConstInParamTyDetector { impl<'v> Visitor<'v> for AnonConstInParamTyDetector { fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) { - if let GenericParamKind::Const { ty, default: _ } = p.kind { + if let GenericParamKind::Const { ty, default: _, is_host_effect: _ } = p.kind { let prev = self.in_param_ty; self.in_param_ty = true; self.visit_ty(ty); diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index d746e6dea..39ca1bba0 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -34,17 +34,14 @@ fn associated_type_bounds<'tcx>( let trait_def_id = tcx.local_parent(assoc_item_def_id); let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id); - let bounds_from_parent = trait_predicates - .predicates - .iter() - .copied() - .filter(|(pred, _)| match pred.kind().skip_binder() { + let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| { + match pred.kind().skip_binder() { ty::ClauseKind::Trait(tr) => tr.self_ty() == item_ty, ty::ClauseKind::Projection(proj) => proj.projection_ty.self_ty() == item_ty, ty::ClauseKind::TypeOutlives(outlives) => outlives.0 == item_ty, _ => false, - }) - .map(|(clause, span)| (clause, span)); + } + }); let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent)); debug!( @@ -86,7 +83,7 @@ pub(super) fn explicit_item_bounds( // RPITIT's bounds are the same as opaque type bounds, but with // a projection self type. Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { - let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item(); + let item = tcx.hir_node_by_def_id(opaque_def_id.expect_local()).expect_item(); let opaque_ty = item.expect_opaque_ty(); return ty::EarlyBinder::bind(opaque_type_bounds( tcx, @@ -100,13 +97,14 @@ pub(super) fn explicit_item_bounds( item.span, )); } - // These should have been fed! - Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(), + Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!( + tcx.def_span(def_id), + "item bounds for RPITIT in impl to be fed on def-id creation" + ), None => {} } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let bounds = match tcx.hir().get(hir_id) { + let bounds = match tcx.hir_node_by_def_id(def_id) { hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(bounds, _), span, @@ -132,7 +130,7 @@ pub(super) fn explicit_item_bounds( let (hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) = *origin else { - bug!() + span_bug!(*span, "RPITIT cannot be a TAIT, but got origin {origin:?}"); }; let args = GenericArgs::identity_for_item(tcx, def_id); let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 104da581e..41520718a 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -134,8 +134,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen None => {} } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let node = tcx.hir().get(hir_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); + let node = tcx.hir_node(hir_id); let mut is_trait = None; let mut is_default_impl_trait = None; @@ -290,13 +290,18 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } hir::WherePredicate::RegionPredicate(region_pred) => { - let r1 = icx.astconv().ast_region_to_region(®ion_pred.lifetime, None); + let r1 = icx.astconv().ast_region_to_region(region_pred.lifetime, None); predicates.extend(region_pred.bounds.iter().map(|bound| { let (r2, span) = match bound { hir::GenericBound::Outlives(lt) => { (icx.astconv().ast_region_to_region(lt, None), lt.ident.span) } - _ => bug!(), + bound => { + span_bug!( + bound.span(), + "lifetime param bounds must be outlives, but found {bound:?}" + ) + } }; let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)) .to_predicate(tcx); @@ -337,7 +342,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // and the duplicated parameter, to ensure that they do not get out of sync. if let Node::Item(&Item { kind: ItemKind::OpaqueTy(..), .. }) = node { let opaque_ty_id = tcx.hir().parent_id(hir_id); - let opaque_ty_node = tcx.hir().get(opaque_ty_id); + let opaque_ty_node = tcx.hir_node(opaque_ty_id); let Node::Ty(&Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node else { bug!("unexpected {opaque_ty_node:?}") }; @@ -362,10 +367,10 @@ fn compute_bidirectional_outlives_predicates<'tcx>( ) { for param in opaque_own_params { let orig_lifetime = tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()); - if let ty::ReEarlyBound(..) = *orig_lifetime { - let dup_lifetime = ty::Region::new_early_bound( + if let ty::ReEarlyParam(..) = *orig_lifetime { + let dup_lifetime = ty::Region::new_early_param( tcx, - ty::EarlyBoundRegion { def_id: param.def_id, index: param.index, name: param.name }, + ty::EarlyParamRegion { def_id: param.def_id, index: param.index, name: param.name }, ); let span = tcx.def_span(param.def_id); predicates.push(( @@ -412,8 +417,8 @@ fn const_evaluatable_predicates_of( } } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let node = tcx.hir().get(hir_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); + let node = tcx.hir_node(hir_id); let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() }; if let hir::Node::Item(item) = node @@ -503,7 +508,7 @@ pub(super) fn explicit_predicates_of<'tcx>( } } else { if matches!(def_kind, DefKind::AnonConst) && tcx.features().generic_const_exprs { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let parent_def_id = tcx.hir().get_parent_item(hir_id); if let Some(defaulted_param_def_id) = @@ -571,7 +576,7 @@ pub(super) fn explicit_predicates_of<'tcx>( // To fix this, we call `explicit_predicates_of` directly on `foo`, the parent's parent. // In the above example this is `foo::{opaque#0}` or `impl Iterator` - let parent_hir_id = tcx.hir().local_def_id_to_hir_id(parent_def_id.def_id); + let parent_hir_id = tcx.local_def_id_to_hir_id(parent_def_id.def_id); // In the above example this is the function `foo` let item_def_id = tcx.hir().get_parent_item(parent_hir_id); @@ -631,9 +636,9 @@ pub(super) fn implied_predicates_with_filter( return tcx.super_predicates_of(trait_def_id); }; - let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id); + let trait_hir_id = tcx.local_def_id_to_hir_id(trait_def_id); - let Node::Item(item) = tcx.hir().get(trait_hir_id) else { + let Node::Item(item) = tcx.hir_node(trait_hir_id) else { bug!("trait_node_id {} is not an item", trait_hir_id); }; @@ -691,7 +696,7 @@ pub(super) fn type_param_predicates( // written inline like `<T: Foo>` or in a where-clause like // `where T: Foo`. - let param_id = tcx.hir().local_def_id_to_hir_id(def_id); + let param_id = tcx.local_def_id_to_hir_id(def_id); let param_owner = tcx.hir().ty_param_owner(def_id); let generics = tcx.generics_of(param_owner); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; @@ -712,11 +717,11 @@ pub(super) fn type_param_predicates( .unwrap_or_default(); let mut extend = None; - let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id); - let ast_generics = match tcx.hir().get(item_hir_id) { - Node::TraitItem(item) => &item.generics, + let item_hir_id = tcx.local_def_id_to_hir_id(item_def_id); + let ast_generics = match tcx.hir_node(item_hir_id) { + Node::TraitItem(item) => item.generics, - Node::ImplItem(item) => &item.generics, + Node::ImplItem(item) => item.generics, Node::Item(item) => { match item.kind { diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 6424d1c79..9f0742dad 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -295,7 +295,7 @@ fn late_arg_as_bound_arg<'tcx>( ) -> ty::BoundVariableKind { match arg { ResolvedArg::LateBound(_, _, def_id) => { - let name = tcx.hir().name(tcx.hir().local_def_id_to_hir_id(def_id.expect_local())); + let name = tcx.hir().name(tcx.local_def_id_to_hir_id(def_id.expect_local())); match param.kind { GenericParamKind::Lifetime { .. } => { ty::BoundVariableKind::Region(ty::BrNamed(*def_id, name)) @@ -335,7 +335,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // though this may happen when we call `poly_trait_ref_binder_info` with // an (erroneous, #113423) associated return type bound in an impl header. if !supertrait_bound_vars.is_empty() { - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( DUMMY_SP, format!( "found supertrait lifetimes without a binder to append \ @@ -350,7 +350,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { // Nested poly trait refs have the binders concatenated let mut full_binders = self.map.late_bound_vars.entry(*hir_id).or_default().clone(); - full_binders.extend(supertrait_bound_vars.into_iter()); + full_binders.extend(supertrait_bound_vars); break (full_binders, BinderScopeType::Concatenating); } } @@ -565,7 +565,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let mut bound_vars = FxIndexMap::default(); debug!(?generics.params); for param in generics.params { - let (def_id, reg) = ResolvedArg::early(¶m); + let (def_id, reg) = ResolvedArg::early(param); bound_vars.insert(def_id, reg); } @@ -684,7 +684,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { lifetime: self.map.defs.get(&lifetime_ref.hir_id).cloned(), s: self.scope, }; - self.with(scope, |this| this.visit_ty(&mt.ty)); + self.with(scope, |this| this.visit_ty(mt.ty)); } hir::TyKind::OpaqueDef(item_id, lifetimes, _in_trait) => { // Resolve the lifetimes in the bounds to the lifetime defs in the generics. @@ -733,7 +733,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { let def = self.map.defs.get(&lifetime.hir_id).cloned(); let Some(ResolvedArg::LateBound(_, _, def_id)) = def else { continue }; let Some(def_id) = def_id.as_local() else { continue }; - let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = self.tcx.local_def_id_to_hir_id(def_id); // Ensure that the parent of the def is an item, not HRTB let parent_id = self.tcx.hir().parent_id(hir_id); if !parent_id.is_owner() { @@ -748,7 +748,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } if let hir::Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy { .. }, .. - }) = self.tcx.hir().get(parent_id) + }) = self.tcx.hir_node(parent_id) { let mut err = self.tcx.sess.struct_span_err( lifetime.ident.span, @@ -775,7 +775,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } Type(bounds, ty) => { self.visit_early(trait_item.hir_id(), trait_item.generics, |this| { - this.visit_generics(&trait_item.generics); + this.visit_generics(trait_item.generics); for bound in bounds { this.visit_param_bound(bound); } @@ -847,7 +847,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { hir::FnRetTy::DefaultReturn(_) => None, hir::FnRetTy::Return(ty) => Some(ty), }; - self.visit_fn_like_elision(&fd.inputs, output, matches!(fk, intravisit::FnKind::Closure)); + self.visit_fn_like_elision(fd.inputs, output, matches!(fk, intravisit::FnKind::Closure)); intravisit::walk_fn_kind(self, fk); self.visit_nested_body(body_id) } @@ -894,7 +894,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { }; self.with(scope, |this| { walk_list!(this, visit_generic_param, bound_generic_params); - this.visit_ty(&bounded_ty); + this.visit_ty(bounded_ty); walk_list!(this, visit_param_bound, bounds); }) } @@ -925,7 +925,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { "you can use the `'static` lifetime directly, in place of `{}`", lifetime.ident, ); - lint.help(help) + lint.help(help); }, ); } @@ -938,32 +938,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { } } - fn visit_param_bound(&mut self, bound: &'tcx hir::GenericBound<'tcx>) { - match bound { - hir::GenericBound::LangItemTrait(_, _, hir_id, _) => { - // FIXME(jackh726): This is pretty weird. `LangItemTrait` doesn't go - // through the regular poly trait ref code, so we don't get another - // chance to introduce a binder. For now, I'm keeping the existing logic - // of "if there isn't a Binder scope above us, add one", but I - // imagine there's a better way to go about this. - let (binders, scope_type) = self.poly_trait_ref_binder_info(); - - self.record_late_bound_vars(*hir_id, binders); - let scope = Scope::Binder { - hir_id: *hir_id, - bound_vars: FxIndexMap::default(), - s: self.scope, - scope_type, - where_bound_origin: None, - }; - self.with(scope, |this| { - intravisit::walk_param_bound(this, bound); - }); - } - _ => intravisit::walk_param_bound(self, bound), - } - } - fn visit_poly_trait_ref(&mut self, trait_ref: &'tcx hir::PolyTraitRef<'tcx>) { self.visit_poly_trait_ref_inner(trait_ref, NonLifetimeBinderAllowed::Allow); } @@ -992,7 +966,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { self.visit_ty(ty); } } - GenericParamKind::Const { ty, default } => { + GenericParamKind::Const { ty, default, is_host_effect: _ } => { self.visit_ty(ty); if let Some(default) = default { self.visit_body(self.tcx.hir().body(default.body)); @@ -1004,7 +978,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { fn object_lifetime_default(tcx: TyCtxt<'_>, param_def_id: LocalDefId) -> ObjectLifetimeDefault { debug_assert_eq!(tcx.def_kind(param_def_id), DefKind::TyParam); - let hir::Node::GenericParam(param) = tcx.hir().get_by_def_id(param_def_id) else { + let hir::Node::GenericParam(param) = tcx.hir_node_by_def_id(param_def_id) else { bug!("expected GenericParam for object_lifetime_default"); }; match param.source { @@ -1061,7 +1035,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { { let BoundVarContext { tcx, map, .. } = self; let mut this = BoundVarContext { tcx: *tcx, map, scope: &wrap_scope }; - let span = debug_span!("scope", scope = ?TruncatedScopeDebug(&this.scope)); + let span = debug_span!("scope", scope = ?TruncatedScopeDebug(this.scope)); { let _enter = span.enter(); f(&mut this); @@ -1300,12 +1274,16 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { what, }) } - _ => unreachable!(), + kind => span_bug!( + use_span, + "did not expect to resolve lifetime to {}", + kind.descr(param_def_id) + ), }; def = ResolvedArg::Error(guar); } else if let Some(body_id) = outermost_body { let fn_id = self.tcx.hir().body_owner(body_id); - match self.tcx.hir().get(fn_id) { + match self.tcx.hir_node(fn_id) { Node::Item(hir::Item { owner_id, kind: hir::ItemKind::Fn(..), .. }) | Node::TraitItem(hir::TraitItem { owner_id, @@ -1363,7 +1341,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } } - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( lifetime_ref.ident.span, format!("Could not resolve {:?} in scope {:#?}", lifetime_ref, self.scope,), ); @@ -1441,7 +1419,11 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { what, }) } - _ => unreachable!(), + kind => span_bug!( + use_span, + "did not expect to resolve non-lifetime param to {}", + kind.descr(param_def_id.to_def_id()) + ), }; self.map.defs.insert(hir_id, ResolvedArg::Error(guar)); } else { @@ -1493,7 +1475,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } } - self.tcx.sess.delay_span_bug( + self.tcx.sess.span_delayed_bug( self.tcx.hir().span(hir_id), format!("could not resolve {param_def_id:?}"), ); @@ -1724,7 +1706,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } else { self.tcx .sess - .delay_span_bug(binding.ident.span, "bad return type notation here"); + .span_delayed_bug(binding.ident.span, "bad return type notation here"); vec![] }; self.with(scope, |this| { @@ -1848,8 +1830,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) { - debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref); let mut late_depth = 0; let mut scope = self.scope; let lifetime = loop { @@ -2012,7 +1994,7 @@ fn is_late_bound_map( fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<!> { debug!("r={:?}", r.kind()); - if let ty::RegionKind::ReEarlyBound(region) = r.kind() { + if let ty::RegionKind::ReEarlyParam(region) = r.kind() { self.arg_is_constrained[region.index as usize] = true; } @@ -2057,7 +2039,7 @@ fn is_late_bound_map( Some(true) => Some(arg), Some(false) => None, None => { - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( *span, format!( "Incorrect generic arg count for alias {alias_def:?}" @@ -2122,8 +2104,8 @@ pub fn deny_non_region_late_bound( let mut first = true; for (var, arg) in bound_vars { - let Node::GenericParam(param) = tcx.hir().get_by_def_id(*var) else { - bug!(); + let Node::GenericParam(param) = tcx.hir_node_by_def_id(*var) else { + span_bug!(tcx.def_span(*var), "expected bound-var def-id to resolve to param"); }; let what = match param.kind { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index d7bd2a7b1..19e7fe388 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -18,12 +18,18 @@ mod opaque; fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { use hir::*; use rustc_middle::ty::Ty; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); - let Node::AnonConst(_) = tcx.hir().get(hir_id) else { panic!() }; + let node = tcx.hir_node(hir_id); + let Node::AnonConst(_) = node else { + span_bug!( + tcx.def_span(def_id), + "expected anon const in `anon_const_type_of`, got {node:?}" + ); + }; let parent_node_id = tcx.hir().parent_id(hir_id); - let parent_node = tcx.hir().get(parent_node_id); + let parent_node = tcx.hir_node(parent_node_id); let (generics, arg_idx) = match parent_node { // Easy case: arrays repeat expressions. @@ -61,7 +67,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> { } Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. }) - if let Node::TraitRef(trait_ref) = tcx.hir().get(tcx.hir().parent_id(binding_id)) => + if let Node::TraitRef(trait_ref) = tcx.hir_node(tcx.hir().parent_id(binding_id)) => { let Some(trait_def_id) = trait_ref.trait_def_id() else { return Ty::new_error_with_message( @@ -350,11 +356,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty } } - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let icx = ItemCtxt::new(tcx, def_id); - let output = match tcx.hir().get(hir_id) { + let output = match tcx.hir_node(hir_id) { Node::TraitItem(item) => match item.kind { TraitItemKind::Fn(..) => { let args = ty::GenericArgs::identity_for_item(tcx, def_id); @@ -475,7 +481,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty }, Node::Ctor(def) | Node::Variant(Variant { data: def, .. }) => match def { - VariantData::Unit(..) | VariantData::Struct(..) => { + VariantData::Unit(..) | VariantData::Struct { .. } => { tcx.type_of(tcx.hir().get_parent_item(hir_id)).instantiate_identity() } VariantData::Tuple(..) => { @@ -517,8 +523,7 @@ pub(super) fn type_of_opaque( if let Some(def_id) = def_id.as_local() { use rustc_hir::*; - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - Ok(ty::EarlyBinder::bind(match tcx.hir().get(hir_id) { + Ok(ty::EarlyBinder::bind(match tcx.hir_node_by_def_id(def_id) { Node::Item(item) => match item.kind { ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias { .. }, @@ -569,7 +574,7 @@ fn infer_placeholder_type<'a>( // then the user may have written e.g. `const A = 42;`. // In this case, the parser has stashed a diagnostic for // us to improve in typeck so we do that now. - match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) { + match tcx.sess.dcx().steal_diagnostic(span, StashKey::ItemNoType) { Some(mut err) => { if !ty.references_error() { // Only suggest adding `:` if it was missing (and suggested by parsing diagnostic) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index e8ab2651d..3785b61f2 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -41,7 +41,7 @@ pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) { /// ``` #[instrument(skip(tcx), level = "debug")] pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); let scope = tcx.hir().get_defining_scope(hir_id); let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] }; @@ -50,8 +50,8 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local if scope == hir::CRATE_HIR_ID { tcx.hir().walk_toplevel_module(&mut locator); } else { - trace!("scope={:#?}", tcx.hir().get(scope)); - match tcx.hir().get(scope) { + trace!("scope={:#?}", tcx.hir_node(scope)); + match tcx.hir_node(scope) { // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods // This allows our visitor to process the defining item itself, causing // it to pick up any 'sibling' defining uses. @@ -95,7 +95,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local let reported = tcx.sess.emit_err(UnconstrainedOpaqueType { span: tcx.def_span(def_id), name: tcx.item_name(parent_def_id.to_def_id()), - what: match tcx.hir().get(scope) { + what: match tcx.hir_node(scope) { _ if scope == hir::CRATE_HIR_ID => "module", Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module", Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl", @@ -278,11 +278,15 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( let mir_opaque_ty = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied(); if let Some(mir_opaque_ty) = mir_opaque_ty { - let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id); + if mir_opaque_ty.references_error() { + return mir_opaque_ty.ty; + } + + let scope = tcx.local_def_id_to_hir_id(owner_def_id); debug!(?scope); let mut locator = RpitConstraintChecker { def_id, tcx, found: mir_opaque_ty }; - match tcx.hir().get(scope) { + match tcx.hir_node(scope) { Node::Item(it) => intravisit::walk_item(&mut locator, it), Node::ImplItem(it) => intravisit::walk_impl_item(&mut locator, it), Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it), diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index ed5e9dd2b..65d1ffa40 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -13,8 +13,8 @@ impl From<ty::ParamTy> for Parameter { } } -impl From<ty::EarlyBoundRegion> for Parameter { - fn from(param: ty::EarlyBoundRegion) -> Self { +impl From<ty::EarlyParamRegion> for Parameter { + fn from(param: ty::EarlyParamRegion) -> Self { Parameter(param.index) } } @@ -73,7 +73,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ParameterCollector { } fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - if let ty::ReEarlyBound(data) = *r { + if let ty::ReEarlyParam(data) = *r { self.parameters.push(Parameter::from(data)); } ControlFlow::Continue(()) diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index dd83b5b6f..f461b6a94 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -2,14 +2,126 @@ use crate::fluent_generated as fluent; use rustc_errors::{ - error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic, + error_code, Applicability, DiagCtxt, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, MultiSpan, }; use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic}; -use rustc_middle::ty::{self, print::TraitRefPrintOnlyTraitPath, Ty}; +use rustc_middle::ty::Ty; use rustc_span::{symbol::Ident, Span, Symbol}; #[derive(Diagnostic)] +#[diag(hir_analysis_ambiguous_assoc_item)] +pub struct AmbiguousAssocItem<'a> { + #[primary_span] + #[label] + pub span: Span, + pub assoc_kind: &'static str, + pub assoc_name: Ident, + pub ty_param_name: &'a str, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_assoc_kind_mismatch)] +pub struct AssocKindMismatch { + #[primary_span] + #[label] + pub span: Span, + pub expected: &'static str, + pub got: &'static str, + #[label(hir_analysis_expected_because_label)] + pub expected_because_label: Option<Span>, + pub assoc_kind: &'static str, + #[note] + pub def_span: Span, + #[label(hir_analysis_bound_on_assoc_const_label)] + pub bound_on_assoc_const_label: Option<Span>, + #[subdiagnostic] + pub wrap_in_braces_sugg: Option<AssocKindMismatchWrapInBracesSugg>, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg, + applicability = "maybe-incorrect" +)] +pub struct AssocKindMismatchWrapInBracesSugg { + #[suggestion_part(code = "{{ ")] + pub lo: Span, + #[suggestion_part(code = " }}")] + pub hi: Span, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_assoc_item_not_found, code = "E0220")] +pub struct AssocItemNotFound<'a> { + #[primary_span] + pub span: Span, + pub assoc_name: Ident, + pub assoc_kind: &'static str, + pub ty_param_name: &'a str, + #[subdiagnostic] + pub label: Option<AssocItemNotFoundLabel<'a>>, + #[subdiagnostic] + pub sugg: Option<AssocItemNotFoundSugg<'a>>, +} + +#[derive(Subdiagnostic)] +pub enum AssocItemNotFoundLabel<'a> { + #[label(hir_analysis_assoc_item_not_found_label)] + NotFound { + #[primary_span] + span: Span, + }, + #[label(hir_analysis_assoc_item_not_found_found_in_other_trait_label)] + FoundInOtherTrait { + #[primary_span] + span: Span, + assoc_kind: &'static str, + trait_name: &'a str, + suggested_name: Symbol, + identically_named: bool, + }, +} + +#[derive(Subdiagnostic)] + +pub enum AssocItemNotFoundSugg<'a> { + #[suggestion( + hir_analysis_assoc_item_not_found_similar_sugg, + code = "{suggested_name}", + applicability = "maybe-incorrect" + )] + Similar { + #[primary_span] + span: Span, + assoc_kind: &'static str, + suggested_name: Symbol, + }, + #[suggestion( + hir_analysis_assoc_item_not_found_similar_in_other_trait_sugg, + code = "{suggested_name}", + style = "verbose", + applicability = "maybe-incorrect" + )] + SimilarInOtherTrait { + #[primary_span] + span: Span, + assoc_kind: &'static str, + suggested_name: Symbol, + }, + #[suggestion(hir_analysis_assoc_item_not_found_other_sugg, code = "{suggested_name}")] + Other { + #[primary_span] + span: Span, + #[applicability] + applicability: Applicability, + ty_param_name: &'a str, + assoc_kind: &'static str, + suggested_name: Symbol, + }, +} + +#[derive(Diagnostic)] #[diag(hir_analysis_unrecognized_atomic_operation, code = "E0092")] pub struct UnrecognizedAtomicOperation<'a> { #[primary_span] @@ -205,8 +317,8 @@ pub struct MissingTypeParams { // Manual implementation of `IntoDiagnostic` to be able to call `span_to_snippet`. impl<'a> IntoDiagnostic<'a> for MissingTypeParams { #[track_caller] - fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let mut err = handler.struct_span_err_with_code( + fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, ErrorGuaranteed> { + let mut err = dcx.struct_span_err_with_code( self.span, fluent::hir_analysis_missing_type_params, error_code!(E0393), @@ -538,27 +650,6 @@ pub(crate) struct ReturnTypeNotationEqualityBound { } #[derive(Diagnostic)] -#[diag(hir_analysis_return_type_notation_missing_method)] -pub(crate) struct ReturnTypeNotationMissingMethod { - #[primary_span] - pub span: Span, - pub ty_name: String, - pub assoc_name: Symbol, -} - -#[derive(Diagnostic)] -#[diag(hir_analysis_return_type_notation_conflicting_bound)] -#[note] -pub(crate) struct ReturnTypeNotationConflictingBound<'tcx> { - #[primary_span] - pub span: Span, - pub ty_name: String, - pub assoc_name: Symbol, - pub first_bound: ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, - pub second_bound: ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, -} - -#[derive(Diagnostic)] #[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")] pub(crate) struct PlaceholderNotAllowedItemSignatures { #[primary_span] @@ -955,15 +1046,6 @@ pub(crate) struct ReturnPositionImplTraitInTraitRefined<'tcx> { } #[derive(Diagnostic)] -#[diag(hir_analysis_assoc_bound_on_const)] -#[note] -pub struct AssocBoundOnConst { - #[primary_span] - pub span: Span, - pub descr: &'static str, -} - -#[derive(Diagnostic)] #[diag(hir_analysis_inherent_ty_outside, code = "E0390")] #[help] pub struct InherentTyOutside { diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index ca7679cfb..78745fe47 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -5,7 +5,7 @@ use rustc_hir::{ForeignItem, ForeignItemKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::query::Providers; -use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::LocalDefId; use rustc_trait_selection::traits::{self, ObligationCtxt}; @@ -25,11 +25,11 @@ fn diagnostic_hir_wf_check<'tcx>( WellFormedLoc::Ty(def_id) => def_id, WellFormedLoc::Param { function, param_idx: _ } => function, }; - let hir_id = hir.local_def_id_to_hir_id(def_id); + let hir_id = tcx.local_def_id_to_hir_id(def_id); // HIR wfcheck should only ever happen as part of improving an existing error tcx.sess - .delay_span_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!"); + .span_delayed_bug(tcx.def_span(def_id), "Performed HIR wfcheck without an existing error!"); let icx = ItemCtxt::new(tcx, def_id); @@ -68,7 +68,13 @@ fn diagnostic_hir_wf_check<'tcx>( let infcx = self.tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new(&infcx); - let tcx_ty = self.icx.to_ty(ty).fold_with(&mut EraseAllBoundRegions { tcx: self.tcx }); + let tcx_ty = self.icx.to_ty(ty); + // This visitor can walk into binders, resulting in the `tcx_ty` to + // potentially reference escaping bound variables. We simply erase + // those here. + let tcx_ty = self.tcx.fold_regions(tcx_ty, |r, _| { + if r.is_bound() { self.tcx.lifetimes.re_erased } else { r } + }); let cause = traits::ObligationCause::new( ty.span, self.def_id, @@ -116,7 +122,7 @@ fn diagnostic_hir_wf_check<'tcx>( // We will walk 'into' this type to try to find // a more precise span for our predicate. let tys = match loc { - WellFormedLoc::Ty(_) => match hir.get(hir_id) { + WellFormedLoc::Ty(_) => match tcx.hir_node(hir_id) { hir::Node::ImplItem(item) => match item.kind { hir::ImplItemKind::Type(ty) => vec![ty], hir::ImplItemKind::Const(ty, _) => vec![ty], @@ -178,24 +184,3 @@ fn diagnostic_hir_wf_check<'tcx>( } visitor.cause } - -struct EraseAllBoundRegions<'tcx> { - tcx: TyCtxt<'tcx>, -} - -// Higher ranked regions are complicated. -// To make matters worse, the HIR WF check can instantiate them -// outside of a `Binder`, due to the way we (ab)use -// `ItemCtxt::to_ty`. To make things simpler, we just erase all -// of them, regardless of depth. At worse, this will give -// us an inaccurate span for an error message, but cannot -// lead to unsoundness (we call `delay_span_bug` at the start -// of `diagnostic_hir_wf_check`). -impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseAllBoundRegions<'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.tcx - } - fn fold_region(&mut self, r: Region<'tcx>) -> Region<'tcx> { - if r.is_late_bound() { self.tcx.lifetimes.re_erased } else { r } - } -} diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 788121f7a..fff4a919e 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -74,7 +74,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) if impl_self_ty.references_error() { // Don't complain about unconstrained type params when self ty isn't known due to errors. // (#36836) - tcx.sess.delay_span_bug( + tcx.sess.span_delayed_bug( tcx.def_span(impl_def_id), format!( "potentially unconstrained type parameters weren't evaluated: {impl_self_ty:?}", diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 2b8219c01..91cdffbbe 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -57,9 +57,9 @@ This API is completely unstable and subject to change. #![allow(rustc::potential_query_instability)] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), allow(internal_features))] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] +#![allow(internal_features)] #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(if_let_guard)] @@ -99,8 +99,6 @@ pub mod structured_errors; mod variance; use rustc_errors::ErrorGuaranteed; -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; use rustc_hir as hir; use rustc_middle::middle; use rustc_middle::query::Providers; @@ -115,7 +113,7 @@ use astconv::{AstConv, OnlySelfBounds}; use bounds::Bounds; use rustc_hir::def::DefKind; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) { const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `aapcs`, `win64`, `sysv64` or `efiapi`"; @@ -211,8 +209,8 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module)) }); - // HACK: `check_mod_type_wf` may spuriously emit errors due to `delay_span_bug`, even if those errors - // only actually get emitted in `check_mod_item_types`. + // HACK: `check_mod_type_wf` may spuriously emit errors due to `span_delayed_bug`, even if + // those errors only actually get emitted in `check_mod_item_types`. errs?; if tcx.features().rustc_attrs { diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs index be9d076bd..9541e5107 100644 --- a/compiler/rustc_hir_analysis/src/outlives/mod.rs +++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs @@ -18,7 +18,7 @@ pub fn provide(providers: &mut Providers) { } fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clause<'_>, Span)] { - let id = tcx.hir().local_def_id_to_hir_id(item_def_id); + let id = tcx.local_def_id_to_hir_id(item_def_id); if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) && tcx.features().generic_const_exprs @@ -41,7 +41,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau } } - match tcx.hir().get(id) { + match tcx.hir_node(id) { Node::Item(item) => match item.kind { hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..) => { let crate_map = tcx.inferred_outlives_crate(()); diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs index a6410c944..8077acea5 100644 --- a/compiler/rustc_hir_analysis/src/outlives/utils.rs +++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs @@ -80,6 +80,10 @@ pub(crate) fn insert_outlives_predicate<'tcx>( .or_insert(span); } + Component::Placeholder(_) => { + span_bug!(span, "Should not deduce placeholder outlives component"); + } + Component::Alias(alias_ty) => { // This would either arise from something like: // @@ -146,11 +150,11 @@ fn is_free_region(region: Region<'_>) -> bool { // These correspond to `T: 'a` relationships: // // struct Foo<'a, T> { - // field: &'a T, // this would generate a ReEarlyBound referencing `'a` + // field: &'a T, // this would generate a ReEarlyParam referencing `'a` // } // // We care about these, so fall through. - ty::ReEarlyBound(_) => true, + ty::ReEarlyParam(_) => true, // These correspond to `T: 'static` relationships which can be // rather surprising. @@ -167,13 +171,13 @@ fn is_free_region(region: Region<'_>) -> bool { // } // // The type above might generate a `T: 'b` bound, but we can - // ignore it. We can't put it on the struct header anyway. - ty::ReLateBound(..) => false, + // ignore it. We can't name this lifetime pn the struct header anyway. + ty::ReBound(..) => false, ty::ReError(_) => false, // These regions don't appear in types from type declarations: - ty::ReErased | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReFree(..) => { + ty::ReErased | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReLateParam(..) => { bug!("unexpected region in outlives inference: {:?}", region); } } diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index 76bd370a6..fab841e36 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -137,10 +137,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { // is from the 'of_trait' field of the enclosing impl let parent = self.tcx.hir().get_parent(self.path_segment.hir_id); - let parent_item = self - .tcx - .hir() - .get_by_def_id(self.tcx.hir().get_parent_item(self.path_segment.hir_id).def_id); + let parent_item = self.tcx.hir_node_by_def_id( + self.tcx.hir().get_parent_item(self.path_segment.hir_id).def_id, + ); // Get the HIR id of the trait ref let hir::Node::TraitRef(hir::TraitRef { hir_ref_id: trait_ref_id, .. }) = parent else { @@ -774,7 +773,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { ); if let Some(parent_node) = self.tcx.hir().opt_parent_id(self.path_segment.hir_id) - && let Some(parent_node) = self.tcx.hir().find(parent_node) + && let Some(parent_node) = self.tcx.opt_hir_node(parent_node) && let hir::Node::Expr(expr) = parent_node { match &expr.kind { diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 5f8b1ace6..f09594cbb 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -413,20 +413,22 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { variance: VarianceTermPtr<'a>, ) { match *region { - ty::ReEarlyBound(ref data) => { + ty::ReEarlyParam(ref data) => { self.add_constraint(current, data.index, variance); } ty::ReStatic => {} - ty::ReLateBound(..) => { - // Late-bound regions do not get substituted the same - // way early-bound regions do, so we skip them here. + ty::ReBound(..) => { + // Either a higher-ranked region inside of a type or a + // late-bound function parameter. + // + // We do not compute constraints for either of these. } ty::ReError(_) => {} - ty::ReFree(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => { + ty::ReLateParam(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => { // We don't expect to see anything but 'static or bound // regions when visiting member types or method types. bug!( diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 9fb39a0e9..410706110 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -106,7 +106,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc impl<'tcx> ty::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeLifetimeCollector<'tcx> { #[instrument(level = "trace", skip(self), ret)] fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> { - if let ty::RegionKind::ReEarlyBound(ebr) = r.kind() { + if let ty::RegionKind::ReEarlyParam(ebr) = r.kind() { self.variances[ebr.index as usize] = ty::Invariant; } ControlFlow::Continue(()) |