From dc0db358abe19481e475e10c32149b53370f1a1c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:57:31 +0200 Subject: Merging upstream version 1.72.1+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_hir_analysis/src/astconv/mod.rs | 1296 +++--------------------- 1 file changed, 151 insertions(+), 1145 deletions(-) (limited to 'compiler/rustc_hir_analysis/src/astconv/mod.rs') diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 2c60a0624..3d6984628 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2,53 +2,45 @@ //! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an //! instance of `AstConv`. +mod bounds; mod errors; pub mod generics; +mod lint; +mod object_safety; use crate::astconv::errors::prohibit_assoc_ty_binding; use crate::astconv::generics::{check_generic_arg_count, create_substs_for_generic_args}; use crate::bounds::Bounds; use crate::collect::HirPlaceholderCollector; -use crate::errors::{ - AmbiguousLifetimeBound, MultipleRelaxedDefaultBounds, TraitObjectDeclaredWithNoTraits, - TypeofReservedKeywordUsed, ValueOfAssociatedStructAlreadySpecified, -}; +use crate::errors::{AmbiguousLifetimeBound, TypeofReservedKeywordUsed}; use crate::middle::resolve_bound_vars as rbv; 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, StashKey, + 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::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; -use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::middle::stability::AllowUnstable; -use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef}; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; -use rustc_middle::ty::{DynKind, ToPredicate}; -use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS}; +use rustc_session::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{kw, Ident, Symbol}; use rustc_span::{sym, Span, DUMMY_SP}; use rustc_target::spec::abi; -use rustc_trait_selection::traits::error_reporting::{ - report_object_safety_error, suggestions::NextTypeParamName, -}; use rustc_trait_selection::traits::wf::object_region_bounds; -use rustc_trait_selection::traits::{self, astconv_object_safety_violations, ObligationCtxt}; +use rustc_trait_selection::traits::{self, NormalizeExt, ObligationCtxt}; +use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; -use smallvec::{smallvec, SmallVec}; -use std::collections::BTreeSet; use std::fmt::Display; use std::slice; @@ -58,6 +50,24 @@ pub struct PathSeg(pub DefId, pub usize); #[derive(Copy, Clone, Debug)] pub struct OnlySelfBounds(pub bool); +#[derive(Copy, Clone, Debug)] +pub enum PredicateFilter { + /// All predicates may be implied by the trait. + All, + + /// Only traits that reference `Self: ..` are implied by the trait. + SelfOnly, + + /// Only traits that reference `Self: ..` and define an associated type + /// with the given ident are implied by the trait. + SelfThatDefines(Ident), + + /// Only traits that reference `Self: ..` and their associated type bounds. + /// For example, given `Self: Tr`, this would expand to `Self: Tr` + /// and `::A: B`. + SelfAndAssociatedTypeBounds, +} + pub trait AstConv<'tcx> { fn tcx(&self) -> TyCtxt<'tcx>; @@ -239,7 +249,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { var: ty::BoundVar::from_u32(index), kind: ty::BrNamed(def_id, name), }; - tcx.mk_re_late_bound(debruijn, br) + ty::Region::new_late_bound(tcx, debruijn, br) } Some(rbv::ResolvedArg::EarlyBound(def_id)) => { @@ -247,12 +257,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]; - tcx.mk_re_early_bound(ty::EarlyBoundRegion { def_id, index, name }) + ty::Region::new_early_bound(tcx, ty::EarlyBoundRegion { def_id, index, name }) } Some(rbv::ResolvedArg::Free(scope, id)) => { let name = lifetime_name(id.expect_local()); - tcx.mk_re_free(scope, ty::BrNamed(id, name)) + ty::Region::new_free(tcx, scope, ty::BrNamed(id, name)) // (*) -- not late-bound, won't change } @@ -269,7 +279,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // elision. `resolve_lifetime` should have // reported an error in this case -- but if // not, let's error out. - tcx.mk_re_error_with_message( + ty::Region::new_error_with_message( + tcx, lifetime.ident.span, "unelided lifetime in signature", ) @@ -432,7 +443,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if let (hir::TyKind::Infer, false) = (&ty.kind, self.astconv.allow_ty_infer()) { self.inferred_params.push(ty.span); - tcx.ty_error_misc().into() + Ty::new_misc_error(tcx).into() } else { self.astconv.ast_ty_to_ty(ty).into() } @@ -463,7 +474,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.astconv.ct_infer(ty, Some(param), inf.span).into() } else { self.inferred_params.push(inf.span); - tcx.const_error_misc(ty).into() + ty::Const::new_misc_error(tcx, ty).into() } } _ => unreachable!(), @@ -485,7 +496,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!(?param, "unelided lifetime in signature"); // This indicates an illegal lifetime in a non-assoc-trait position - tcx.mk_re_error_with_message( + ty::Region::new_error_with_message( + tcx, self.span, "unelided lifetime in signature", ) @@ -500,14 +512,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { _ => false, }) { // Avoid ICE #86756 when type error recovery goes awry. - return tcx.ty_error_misc().into(); + return Ty::new_misc_error(tcx).into(); } tcx.at(self.span).type_of(param.def_id).subst(tcx, substs).into() } else if infer_args { self.astconv.ty_infer(Some(param), self.span).into() } else { // We've already errored above about the mismatch. - tcx.ty_error_misc().into() + Ty::new_misc_error(tcx).into() } } GenericParamDefKind::Const { has_default } => { @@ -517,7 +529,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .no_bound_vars() .expect("const parameter types cannot be generic"); if let Err(guar) = ty.error_reported() { - return tcx.const_error(ty, guar).into(); + return ty::Const::new_error(tcx, guar, ty).into(); } if !infer_args && has_default { tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into() @@ -526,7 +538,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.astconv.ct_infer(ty, Some(param), self.span).into() } else { // We've already errored above about the mismatch. - tcx.const_error_misc(ty).into() + ty::Const::new_misc_error(tcx, ty).into() } } } @@ -884,551 +896,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .is_some() } - /// Sets `implicitly_sized` to true on `Bounds` if necessary - pub(crate) fn add_implicitly_sized( - &self, - bounds: &mut Bounds<'tcx>, - self_ty: Ty<'tcx>, - ast_bounds: &'tcx [hir::GenericBound<'tcx>], - self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, - span: Span, - ) { - let tcx = self.tcx(); - - // Try to find an unbound in bounds. - let mut unbound = None; - let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| { - for ab in ast_bounds { - if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab { - if unbound.is_none() { - unbound = Some(&ptr.trait_ref); - } else { - tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span }); - } - } - } - }; - search_bounds(ast_bounds); - if let Some((self_ty, where_clause)) = self_ty_where_predicates { - for clause in where_clause { - if let hir::WherePredicate::BoundPredicate(pred) = clause { - if pred.is_param_bound(self_ty.to_def_id()) { - search_bounds(pred.bounds); - } - } - } - } - - let sized_def_id = tcx.lang_items().sized_trait(); - match (&sized_def_id, unbound) { - (Some(sized_def_id), Some(tpb)) - if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) => - { - // There was in fact a `?Sized` bound, return without doing anything - return; - } - (_, Some(_)) => { - // There was a `?Trait` bound, but it was not `?Sized`; warn. - tcx.sess.span_warn( - span, - "default bound relaxed for a type parameter, but \ - this does nothing because the given bound is not \ - a default; only `?Sized` is supported", - ); - // Otherwise, add implicitly sized if `Sized` is available. - } - _ => { - // There was no `?Sized` bound; add implicitly sized if `Sized` is available. - } - } - if sized_def_id.is_none() { - // No lang item for `Sized`, so we can't add it as a bound. - return; - } - bounds.push_sized(tcx, self_ty, span); - } - - /// This helper takes a *converted* parameter type (`param_ty`) - /// and an *unconverted* list of bounds: - /// - /// ```text - /// fn foo - /// ^ ^^^^^ `ast_bounds` parameter, in HIR form - /// | - /// `param_ty`, in ty form - /// ``` - /// - /// It adds these `ast_bounds` into the `bounds` structure. - /// - /// **A note on binders:** there is an implied binder around - /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` - /// for more details. - #[instrument(level = "debug", skip(self, ast_bounds, bounds))] - pub(crate) fn add_bounds<'hir, I: Iterator>>( - &self, - param_ty: Ty<'tcx>, - ast_bounds: I, - bounds: &mut Bounds<'tcx>, - bound_vars: &'tcx ty::List, - only_self_bounds: OnlySelfBounds, - ) { - for ast_bound in ast_bounds { - match ast_bound { - hir::GenericBound::Trait(poly_trait_ref, modifier) => { - let (constness, polarity) = match modifier { - hir::TraitBoundModifier::MaybeConst => { - (ty::BoundConstness::ConstIfConst, ty::ImplPolarity::Positive) - } - hir::TraitBoundModifier::None => { - (ty::BoundConstness::NotConst, ty::ImplPolarity::Positive) - } - hir::TraitBoundModifier::Negative => { - (ty::BoundConstness::NotConst, ty::ImplPolarity::Negative) - } - hir::TraitBoundModifier::Maybe => continue, - }; - let _ = self.instantiate_poly_trait_ref( - &poly_trait_ref.trait_ref, - poly_trait_ref.span, - constness, - polarity, - param_ty, - bounds, - false, - 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( - self.tcx(), - ty::Binder::bind_with_vars( - ty::OutlivesPredicate(param_ty, region), - bound_vars, - ), - lifetime.ident.span, - ); - } - } - } - } - - /// Translates a list of bounds from the HIR into the `Bounds` data structure. - /// The self-type for the bounds is given by `param_ty`. - /// - /// Example: - /// - /// ```ignore (illustrative) - /// fn foo() { } - /// // ^ ^^^^^^^^^ ast_bounds - /// // param_ty - /// ``` - /// - /// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be - /// considered `Sized` unless there is an explicit `?Sized` bound. This would be true in the - /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`. - /// - /// `span` should be the declaration size of the parameter. - pub(crate) fn compute_bounds( - &self, - param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], - only_self_bounds: OnlySelfBounds, - ) -> Bounds<'tcx> { - let mut bounds = Bounds::default(); - self.add_bounds( - param_ty, - ast_bounds.iter(), - &mut bounds, - ty::List::empty(), - only_self_bounds, - ); - debug!(?bounds); - - bounds - } - - /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type - /// named `assoc_name` into ty::Bounds. Ignore the rest. - pub(crate) fn compute_bounds_that_match_assoc_item( - &self, - param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], - assoc_name: Ident, - ) -> Bounds<'tcx> { - let mut result = Vec::new(); - - for ast_bound in ast_bounds { - if let Some(trait_ref) = ast_bound.trait_ref() - && let Some(trait_did) = trait_ref.trait_def_id() - && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name) - { - result.push(ast_bound.clone()); - } - } - - let mut bounds = Bounds::default(); - self.add_bounds( - param_ty, - result.iter(), - &mut bounds, - ty::List::empty(), - OnlySelfBounds(true), - ); - debug!(?bounds); - - bounds - } - - /// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates - /// onto `bounds`. - /// - /// **A note on binders:** given something like `T: for<'a> Iterator`, the - /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside* - /// the binder (e.g., `&'a u32`) and hence may reference bound regions. - #[instrument(level = "debug", skip(self, bounds, speculative, dup_bindings, path_span))] - fn add_predicates_for_ast_type_binding( - &self, - hir_ref_id: hir::HirId, - trait_ref: ty::PolyTraitRef<'tcx>, - binding: &ConvertedBinding<'_, 'tcx>, - bounds: &mut Bounds<'tcx>, - speculative: bool, - dup_bindings: &mut FxHashMap, - path_span: Span, - constness: ty::BoundConstness, - only_self_bounds: OnlySelfBounds, - polarity: ty::ImplPolarity, - ) -> Result<(), ErrorGuaranteed> { - // Given something like `U: SomeTrait`, we want to produce a - // predicate like `::T = X`. This is somewhat - // subtle in the event that `T` is defined in a supertrait of - // `SomeTrait`, because in that case we need to upcast. - // - // That is, consider this case: - // - // ``` - // trait SubTrait: SuperTrait { } - // trait SuperTrait { type T; } - // - // ... B: SubTrait ... - // ``` - // - // We want to produce `>::T == foo`. - - 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 - } 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( - trait_ref.def_id(), - ty::AssocKind::Type, - binding.item_name, - ) { - // Simple case: X 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( - || traits::supertraits(tcx, trait_ref), - trait_ref.skip_binder().print_only_trait_name(), - binding.item_name, - path_span, - match binding.kind { - ConvertedBindingKind::Equality(term) => Some(term), - _ => None, - }, - )? - }; - - 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"); - - if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) { - tcx.sess - .struct_span_err( - binding.span, - format!("{} `{}` is private", assoc_item.kind, binding.item_name), - ) - .span_label(binding.span, format!("private {}", assoc_item.kind)) - .emit(); - } - tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); - - if !speculative { - dup_bindings - .entry(assoc_item.def_id) - .and_modify(|prev_span| { - tcx.sess.emit_err(ValueOfAssociatedStructAlreadySpecified { - span: binding.span, - prev_span: *prev_span, - item_name: binding.item_name, - def_path: tcx.def_path_str(assoc_item.container_id(tcx)), - }); - }) - .or_insert(binding.span); - } - - let projection_ty = if return_type_notation { - // If we have an method return type bound, then we need to substitute - // the method's early bound params with suitable late-bound params. - let mut num_bound_vars = candidate.bound_vars().len(); - let substs = - candidate.skip_binder().substs.extend_to(tcx, assoc_item.def_id, |param, _| { - let subst = match param.kind { - GenericParamDefKind::Lifetime => tcx - .mk_re_late_bound( - ty::INNERMOST, - ty::BoundRegion { - var: ty::BoundVar::from_usize(num_bound_vars), - kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name), - }, - ) - .into(), - GenericParamDefKind::Type { .. } => tcx - .mk_bound( - ty::INNERMOST, - ty::BoundTy { - var: ty::BoundVar::from_usize(num_bound_vars), - kind: ty::BoundTyKind::Param(param.def_id, param.name), - }, - ) - .into(), - GenericParamDefKind::Const { .. } => { - let ty = tcx - .type_of(param.def_id) - .no_bound_vars() - .expect("ct params cannot have early bound vars"); - tcx.mk_const( - ty::ConstKind::Bound( - ty::INNERMOST, - ty::BoundVar::from_usize(num_bound_vars), - ), - ty, - ) - .into() - } - }; - num_bound_vars += 1; - subst - }); - - // Next, we need to check that the return-type notation is being used on - // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait). - let output = tcx.fn_sig(assoc_item.def_id).skip_binder().output(); - let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind() - && tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder - { - alias_ty - } else { - return Err(self.tcx().sess.emit_err( - crate::errors::ReturnTypeNotationOnNonRpitit { - span: binding.span, - ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output), - fn_span: tcx.hir().span_if_local(assoc_item.def_id), - note: (), - }, - )); - }; - - // Finally, move the fn return type's bound vars over to account for the early bound - // params (and trait ref's late bound params). This logic is very similar to - // `Predicate::subst_supertrait`, and it's no coincidence why. - let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output); - let subst_output = ty::EarlyBinder(shifted_output).subst(tcx, substs); - - let bound_vars = tcx.late_bound_vars(binding.hir_id); - ty::Binder::bind_with_vars(subst_output, bound_vars) - } else { - // Include substitutions for generic parameters of associated types - candidate.map_bound(|trait_ref| { - let ident = Ident::new(assoc_item.name, binding.item_name.span); - let item_segment = hir::PathSegment { - ident, - hir_id: binding.hir_id, - res: Res::Err, - args: Some(binding.gen_args), - infer_args: false, - }; - - let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item( - path_span, - assoc_item.def_id, - &item_segment, - trait_ref.substs, - ); - - debug!(?substs_trait_ref_and_assoc_item); - - tcx.mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item) - }) - }; - - if !speculative { - // Find any late-bound regions declared in `ty` that are not - // declared in the trait-ref or assoc_item. These are not well-formed. - // - // Example: - // - // for<'a> ::Item = &'a str // <-- 'a is bad - // for<'a> >::Output = &'a str // <-- 'a is ok - if let ConvertedBindingKind::Equality(ty) = binding.kind { - 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)); - debug!(?late_bound_in_trait_ref); - debug!(?late_bound_in_ty); - - // FIXME: point at the type params that don't have appropriate lifetimes: - // struct S1 Fn(&i32, &i32) -> &'a i32>(F); - // ---- ---- ^^^^^^^ - self.validate_late_bound_regions( - late_bound_in_trait_ref, - late_bound_in_ty, - |br_name| { - struct_span_err!( - tcx.sess, - binding.span, - E0582, - "binding for associated type `{}` references {}, \ - which does not appear in the trait input types", - binding.item_name, - br_name - ) - }, - ); - } - } - - match binding.kind { - ConvertedBindingKind::Equality(..) if return_type_notation => { - return Err(self.tcx().sess.emit_err( - crate::errors::ReturnTypeNotationEqualityBound { span: binding.span }, - )); - } - ConvertedBindingKind::Equality(mut term) => { - // "Desugar" a constraint like `T: Iterator` this to - // the "projection predicate" for: - // - // `::Item = u32` - let assoc_item_def_id = projection_ty.skip_binder().def_id; - let def_kind = tcx.def_kind(assoc_item_def_id); - match (def_kind, term.unpack()) { - (hir::def::DefKind::AssocTy, ty::TermKind::Ty(_)) - | (hir::def::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 hir::def::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 { - hir::def::DefKind::AssocTy => tcx.ty_error(reported).into(), - hir::def::DefKind::AssocConst => tcx - .const_error( - tcx.type_of(assoc_item_def_id) - .subst(tcx, projection_ty.skip_binder().substs), - reported, - ) - .into(), - _ => unreachable!(), - }; - } - } - bounds.push_projection_bound( - tcx, - projection_ty - .map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }), - binding.span, - ); - } - ConvertedBindingKind::Constraint(ast_bounds) => { - // "Desugar" a constraint like `T: Iterator` to - // - // `::Item: Debug` - // - // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` - // parameter to have a skipped binder. - // - // NOTE: If `only_self_bounds` is true, do NOT expand this associated - // type bound into a trait predicate, since we only want to add predicates - // for the `Self` type. - if !only_self_bounds.0 { - let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder()); - self.add_bounds( - param_ty, - ast_bounds.iter(), - bounds, - projection_ty.bound_vars(), - only_self_bounds, - ); - } - } - } - Ok(()) - } - fn ast_path_to_ty( &self, span: Span, @@ -1436,384 +903,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { item_segment: &hir::PathSegment<'_>, ) -> Ty<'tcx> { let substs = self.ast_path_substs_for_ty(span, did, item_segment); - self.tcx().at(span).type_of(did).subst(self.tcx(), substs) - } - - fn conv_object_ty_poly_trait_ref( - &self, - span: Span, - hir_trait_bounds: &[hir::PolyTraitRef<'_>], - lifetime: &hir::Lifetime, - borrowed: bool, - representation: DynKind, - ) -> Ty<'tcx> { - let tcx = self.tcx(); - - let mut bounds = Bounds::default(); - let mut potential_assoc_types = Vec::new(); - let dummy_self = self.tcx().types.trait_object_dummy_self; - for trait_bound in hir_trait_bounds.iter().rev() { - if let GenericArgCountResult { - correct: - Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }), - .. - } = self.instantiate_poly_trait_ref( - &trait_bound.trait_ref, - trait_bound.span, - ty::BoundConstness::NotConst, - ty::ImplPolarity::Positive, - dummy_self, - &mut bounds, - false, - // FIXME: This should be `true`, but we don't really handle - // associated type bounds or type aliases in objects in a way - // that makes this meaningful, I think. - OnlySelfBounds(false), - ) { - potential_assoc_types.extend(cur_potential_assoc_types); - } - } - - let mut trait_bounds = vec![]; - let mut projection_bounds = vec![]; - for (pred, span) in bounds.predicates() { - let bound_pred = pred.kind(); - match bound_pred.skip_binder() { - ty::PredicateKind::Clause(clause) => match clause { - ty::Clause::Trait(trait_pred) => { - assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive); - trait_bounds.push(( - bound_pred.rebind(trait_pred.trait_ref), - span, - trait_pred.constness, - )); - } - ty::Clause::Projection(proj) => { - projection_bounds.push((bound_pred.rebind(proj), span)); - } - ty::Clause::TypeOutlives(_) => { - // Do nothing, we deal with regions separately - } - ty::Clause::RegionOutlives(_) | ty::Clause::ConstArgHasType(..) => bug!(), - }, - ty::PredicateKind::WellFormed(_) - | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::ObjectSafe(_) - | ty::PredicateKind::ClosureKind(_, _, _) - | ty::PredicateKind::Subtype(_) - | ty::PredicateKind::Coerce(_) - | ty::PredicateKind::ConstEvaluatable(_) - | ty::PredicateKind::ConstEquate(_, _) - | ty::PredicateKind::TypeWellFormedFromEnv(_) - | ty::PredicateKind::Ambiguous => bug!(), - } - } - - // Expand trait aliases recursively and check that only one regular (non-auto) trait - // is used and no 'maybe' bounds are used. - let expanded_traits = - traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b, _)| (a, b))); - - let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits - .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self) - .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); - if regular_traits.len() > 1 { - let first_trait = ®ular_traits[0]; - let additional_trait = ®ular_traits[1]; - let mut err = struct_span_err!( - tcx.sess, - additional_trait.bottom().1, - E0225, - "only auto traits can be used as additional traits in a trait object" - ); - additional_trait.label_with_exp_info( - &mut err, - "additional non-auto trait", - "additional use", - ); - first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use"); - err.help(format!( - "consider creating a new trait with all of these as supertraits and using that \ - trait here instead: `trait NewTrait: {} {{}}`", - regular_traits - .iter() - .map(|t| t.trait_ref().print_only_trait_path().to_string()) - .collect::>() - .join(" + "), - )); - err.note( - "auto-traits like `Send` and `Sync` are traits that have special properties; \ - for more information on them, visit \ - ", - ); - err.emit(); - } - - if regular_traits.is_empty() && auto_traits.is_empty() { - let trait_alias_span = trait_bounds - .iter() - .map(|&(trait_ref, _, _)| trait_ref.def_id()) - .find(|&trait_ref| tcx.is_trait_alias(trait_ref)) - .map(|trait_ref| tcx.def_span(trait_ref)); - let reported = - tcx.sess.emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span }); - return tcx.ty_error(reported); - } - - // Check that there are no gross object safety violations; - // most importantly, that the supertraits don't contain `Self`, - // to avoid ICEs. - for item in ®ular_traits { - let object_safety_violations = - astconv_object_safety_violations(tcx, item.trait_ref().def_id()); - if !object_safety_violations.is_empty() { - let reported = report_object_safety_error( - tcx, - span, - item.trait_ref().def_id(), - &object_safety_violations, - ) - .emit(); - return tcx.ty_error(reported); - } - } - - // Use a `BTreeSet` to keep output in a more consistent order. - let mut associated_types: FxHashMap> = FxHashMap::default(); - - let regular_traits_refs_spans = trait_bounds - .into_iter() - .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id())); - - for (base_trait_ref, span, constness) in regular_traits_refs_spans { - assert_eq!(constness, ty::BoundConstness::NotConst); - let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx); - for pred in traits::elaborate(tcx, [base_pred]) { - debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred); - - let bound_predicate = pred.kind(); - match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => { - let pred = bound_predicate.rebind(pred); - associated_types.entry(span).or_default().extend( - tcx.associated_items(pred.def_id()) - .in_definition_order() - .filter(|item| item.kind == ty::AssocKind::Type) - .filter(|item| tcx.opt_rpitit_info(item.def_id).is_none()) - .map(|item| item.def_id), - ); - } - ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => { - let pred = bound_predicate.rebind(pred); - // A `Self` within the original bound will be substituted with a - // `trait_object_dummy_self`, so check for that. - let references_self = match pred.skip_binder().term.unpack() { - ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()), - ty::TermKind::Const(c) => { - c.ty().walk().any(|arg| arg == dummy_self.into()) - } - }; - - // If the projection output contains `Self`, force the user to - // elaborate it explicitly to avoid a lot of complexity. - // - // The "classically useful" case is the following: - // ``` - // trait MyTrait: FnMut() -> ::MyOutput { - // type MyOutput; - // } - // ``` - // - // Here, the user could theoretically write `dyn MyTrait`, - // but actually supporting that would "expand" to an infinitely-long type - // `fix $ τ → dyn MyTrait::MyOutput`. - // - // Instead, we force the user to write - // `dyn MyTrait`, which is uglier but works. See - // the discussion in #56288 for alternatives. - if !references_self { - // Include projections defined on supertraits. - projection_bounds.push((pred, span)); - } - } - _ => (), - } - } - } - - for (projection_bound, _) in &projection_bounds { - for def_ids in associated_types.values_mut() { - def_ids.remove(&projection_bound.projection_def_id()); - } - } - - self.complain_about_missing_associated_types( - associated_types, - potential_assoc_types, - hir_trait_bounds, - ); - - // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as - // `dyn Trait + Send`. - // We remove duplicates by inserting into a `FxHashSet` to avoid re-ordering - // the bounds - let mut duplicates = FxHashSet::default(); - auto_traits.retain(|i| duplicates.insert(i.trait_ref().def_id())); - debug!("regular_traits: {:?}", regular_traits); - debug!("auto_traits: {:?}", auto_traits); - - // Erase the `dummy_self` (`trait_object_dummy_self`) used above. - let existential_trait_refs = regular_traits.iter().map(|i| { - i.trait_ref().map_bound(|trait_ref: ty::TraitRef<'tcx>| { - assert_eq!(trait_ref.self_ty(), dummy_self); - - // Verify that `dummy_self` did not leak inside default type parameters. This - // could not be done at path creation, since we need to see through trait aliases. - let mut missing_type_params = vec![]; - let mut references_self = false; - let generics = tcx.generics_of(trait_ref.def_id); - let substs: Vec<_> = trait_ref - .substs - .iter() - .enumerate() - .skip(1) // Remove `Self` for `ExistentialPredicate`. - .map(|(index, arg)| { - if arg == dummy_self.into() { - let param = &generics.params[index]; - missing_type_params.push(param.name); - return tcx.ty_error_misc().into(); - } else if arg.walk().any(|arg| arg == dummy_self.into()) { - references_self = true; - return tcx.ty_error_misc().into(); - } - arg - }) - .collect(); - let substs = tcx.mk_substs(&substs); - - let span = i.bottom().1; - let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| { - hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id) - && hir_bound.span.contains(span) - }); - self.complain_about_missing_type_params( - missing_type_params, - trait_ref.def_id, - span, - empty_generic_args, - ); + let ty = self.tcx().at(span).type_of(did); - if references_self { - let def_id = i.bottom().0.def_id(); - let mut err = struct_span_err!( - tcx.sess, - i.bottom().1, - E0038, - "the {} `{}` cannot be made into an object", - tcx.def_descr(def_id), - tcx.item_name(def_id), - ); - err.note( - rustc_middle::traits::ObjectSafetyViolation::SupertraitSelf(smallvec![]) - .error_msg(), - ); - err.emit(); - } - - ty::ExistentialTraitRef { def_id: trait_ref.def_id, substs } - }) - }); - - let existential_projections = projection_bounds - .iter() - // We filter out traits that don't have `Self` as their self type above, - // we need to do the same for projections. - .filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self) - .map(|(bound, _)| { - bound.map_bound(|mut b| { - assert_eq!(b.projection_ty.self_ty(), dummy_self); - - // Like for trait refs, verify that `dummy_self` did not leak inside default type - // parameters. - let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return true; - } - false - }); - if references_self { - let guar = tcx.sess.delay_span_bug( - span, - "trait object projection bounds reference `Self`", - ); - let substs: Vec<_> = b - .projection_ty - .substs - .iter() - .map(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return tcx.ty_error(guar).into(); - } - arg - }) - .collect(); - b.projection_ty.substs = tcx.mk_substs(&substs); - } - - ty::ExistentialProjection::erase_self_ty(tcx, b) - }) - }); - - let regular_trait_predicates = existential_trait_refs - .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)); - let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| { - ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())) - }); - // N.b. principal, projections, auto traits - // FIXME: This is actually wrong with multiple principals in regards to symbol mangling - let mut v = regular_trait_predicates - .chain( - existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)), - ) - .chain(auto_trait_predicates) - .collect::>(); - v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); - v.dedup(); - let existential_predicates = tcx.mk_poly_existential_predicates(&v); - - // Use explicitly-specified region bound. - let region_bound = if !lifetime.is_elided() { - self.ast_region_to_region(lifetime, None) + if matches!(self.tcx().def_kind(did), DefKind::TyAlias) + && (ty.skip_binder().has_opaque_types() || self.tcx().features().lazy_type_alias) + { + // Type aliases referring to types that contain opaque types (but aren't just directly + // referencing a single opaque type) get encoded as a type alias that normalization will + // then actually instantiate the where bounds of. + let alias_ty = self.tcx().mk_alias_ty(did, substs); + Ty::new_alias(self.tcx(), ty::Weak, alias_ty) } else { - self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| { - if tcx.named_bound_var(lifetime.hir_id).is_some() { - self.ast_region_to_region(lifetime, None) - } else { - self.re_infer(None, span).unwrap_or_else(|| { - let mut err = struct_span_err!( - tcx.sess, - span, - E0228, - "the lifetime bound for this object type cannot be deduced \ - from context; please supply an explicit bound" - ); - let e = if borrowed { - // We will have already emitted an error E0106 complaining about a - // missing named lifetime in `&dyn Trait`, so we elide this one. - err.delay_as_bug() - } else { - err.emit() - }; - tcx.mk_re_error(e) - }) - } - }) - }; - debug!("region_bound: {:?}", region_bound); - - let ty = tcx.mk_dynamic(existential_predicates, region_bound, representation); - debug!("trait_object_type: {:?}", ty); - ty + ty.subst(self.tcx(), substs) + } } fn report_ambiguous_associated_type( @@ -1948,9 +1050,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { || { traits::transitive_bounds_that_define_assoc_item( tcx, - predicates.iter().filter_map(|(p, _)| { - Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref)) - }), + predicates + .iter() + .filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref))), assoc_name, ) }, @@ -2408,6 +1510,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ) -> Result, DefId)>, ErrorGuaranteed> { let tcx = self.tcx(); + // Don't attempt to look up inherent associated types when the feature is not enabled. + // Theoretically it'd be fine to do so since we feature-gate their definition site. + // However, due to current limitations of the implementation (caused by us performing + // selection in AstConv), IATs can lead to cycle errors (#108491, #110106) which mask the + // feature-gate error, needlessly confusing users that use IATs by accident (#113265). + if !tcx.features().inherent_associated_types { + return Ok(None); + } + let candidates: Vec<_> = tcx .inherent_impls(adt_did) .iter() @@ -2441,32 +1552,64 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut fulfillment_errors = Vec::new(); let mut applicable_candidates: Vec<_> = infcx.probe(|_| { - let universe = infcx.create_next_universe(); - // Regions are not considered during selection. - // FIXME(non_lifetime_binders): Here we are "truncating" or "flattening" the universes - // of type and const binders. Is that correct in the selection phase? See also #109505. - let self_ty = tcx.replace_escaping_bound_vars_uncached( - self_ty, - FnMutDelegate { - regions: &mut |_| tcx.lifetimes.re_erased, - types: &mut |bv| { - tcx.mk_placeholder(ty::PlaceholderType { universe, bound: bv }) - }, - consts: &mut |bv, ty| { - tcx.mk_const(ty::PlaceholderConst { universe, bound: bv }, ty) - }, - }, - ); + 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> for BoundVarEraser<'tcx> { + fn interner(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { + if r.is_late_bound() { self.tcx.lifetimes.re_erased } else { r } + } + + 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), + } + } + + fn fold_const( + &mut self, + ct: ty::Const<'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), + } + } + } + + let InferOk { value: self_ty, obligations } = + infcx.at(&cause, param_env).normalize(self_ty); candidates .iter() .copied() .filter(|&(impl_, _)| { infcx.probe(|_| { - let ocx = ObligationCtxt::new_in_snapshot(&infcx); + let ocx = ObligationCtxt::new(&infcx); + ocx.register_obligations(obligations.clone()); - let impl_substs = infcx.fresh_item_substs(impl_); + let impl_substs = infcx.fresh_substs_for_item(span, impl_); let impl_ty = tcx.type_of(impl_).subst(tcx, impl_substs); let impl_ty = ocx.normalize(&cause, param_env, impl_ty); @@ -2522,7 +1665,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .chain(substs.into_iter().skip(parent_substs.len())), ); - let ty = tcx.mk_alias(ty::Inherent, tcx.mk_alias_ty(assoc_item, substs)); + let ty = Ty::new_alias(tcx, ty::Inherent, tcx.mk_alias_ty(assoc_item, substs)); return Ok(Some((ty, assoc_item))); } @@ -2707,7 +1850,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &[path_str], item_segment.ident.name, ); - return tcx.ty_error(reported) + return Ty::new_error(tcx,reported) }; debug!("qpath_to_ty: self_type={:?}", self_ty); @@ -2730,7 +1873,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("qpath_to_ty: trait_ref={:?}", trait_ref); - tcx.mk_projection(item_def_id, item_substs) + Ty::new_projection(tcx, item_def_id, item_substs) } pub fn prohibit_generics<'a>( @@ -2993,7 +2136,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.note("`impl Trait` types can't have type parameters"); }); let substs = self.ast_path_substs_for_ty(span, did, item_segment.0); - tcx.mk_opaque(did, substs) + Ty::new_opaque(tcx, did, substs) } Res::Def( DefKind::Enum @@ -3045,16 +2188,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { var: ty::BoundVar::from_u32(index), kind: ty::BoundTyKind::Param(def_id, name), }; - tcx.mk_bound(debruijn, br) + Ty::new_bound(tcx, debruijn, br) } Some(rbv::ResolvedArg::EarlyBound(_)) => { let def_id = def_id.expect_local(); let item_def_id = tcx.hir().ty_param_owner(def_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id.to_def_id()]; - tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id)) + Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id)) } - Some(rbv::ResolvedArg::Error(guar)) => tcx.ty_error(guar), + Some(rbv::ResolvedArg::Error(guar)) => Ty::new_error(tcx, guar), arg => bug!("unexpected bound var resolution for {hir_id:?}: {arg:?}"), } } @@ -3166,7 +2309,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { err.span_note(impl_.self_ty.span, "not a concrete type"); } - tcx.ty_error(err.emit()) + Ty::new_error(tcx, err.emit()) } else { ty } @@ -3207,9 +2350,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { match prim_ty { hir::PrimTy::Bool => tcx.types.bool, hir::PrimTy::Char => tcx.types.char, - hir::PrimTy::Int(it) => tcx.mk_mach_int(ty::int_ty(it)), - hir::PrimTy::Uint(uit) => tcx.mk_mach_uint(ty::uint_ty(uit)), - hir::PrimTy::Float(ft) => tcx.mk_mach_float(ty::float_ty(ft)), + hir::PrimTy::Int(it) => Ty::new_int(tcx, ty::int_ty(it)), + hir::PrimTy::Uint(uit) => Ty::new_uint(tcx, ty::uint_ty(uit)), + hir::PrimTy::Float(ft) => Ty::new_float(tcx, ty::float_ty(ft)), hir::PrimTy::Str => tcx.types.str_, } } @@ -3219,7 +2362,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .sess .delay_span_bug(path.span, "path with `Res::Err` but no error emitted"); self.set_tainted_by_errors(e); - self.tcx().ty_error(e) + Ty::new_error(self.tcx(), e) } _ => span_bug!(span, "unexpected resolution: {:?}", path.res), } @@ -3244,31 +2387,27 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); let result_ty = match &ast_ty.kind { - hir::TyKind::Slice(ty) => tcx.mk_slice(self.ast_ty_to_ty(ty)), + hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.ast_ty_to_ty(ty)), hir::TyKind::Ptr(mt) => { - tcx.mk_ptr(ty::TypeAndMut { ty: self.ast_ty_to_ty(mt.ty), mutbl: mt.mutbl }) + Ty::new_ptr(tcx, ty::TypeAndMut { ty: self.ast_ty_to_ty(mt.ty), mutbl: mt.mutbl }) } hir::TyKind::Ref(region, mt) => { let r = self.ast_region_to_region(region, None); debug!(?r); let t = self.ast_ty_to_ty_inner(mt.ty, true, false); - tcx.mk_ref(r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl }) + Ty::new_ref(tcx, r, ty::TypeAndMut { ty: t, mutbl: mt.mutbl }) } hir::TyKind::Never => tcx.types.never, hir::TyKind::Tup(fields) => { - tcx.mk_tup_from_iter(fields.iter().map(|t| self.ast_ty_to_ty(t))) + Ty::new_tup_from_iter(tcx, fields.iter().map(|t| self.ast_ty_to_ty(t))) } hir::TyKind::BareFn(bf) => { require_c_abi_if_c_variadic(tcx, bf.decl, bf.abi, ast_ty.span); - tcx.mk_fn_ptr(self.ty_of_fn( - ast_ty.hir_id, - bf.unsafety, - bf.abi, - bf.decl, - None, - Some(ast_ty), - )) + Ty::new_fn_ptr( + tcx, + self.ty_of_fn(ast_ty.hir_id, bf.unsafety, bf.abi, bf.decl, None, Some(ast_ty)), + ) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { self.maybe_lint_bare_trait(ast_ty, in_path); @@ -3277,7 +2416,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { TraitObjectSyntax::DynStar => ty::DynStar, }; - self.conv_object_ty_poly_trait_ref(ast_ty.span, bounds, lifetime, borrowed, repr) + self.conv_object_ty_poly_trait_ref( + ast_ty.span, + ast_ty.hir_id, + bounds, + lifetime, + borrowed, + repr, + ) } hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => { debug!(?maybe_qself, ?path); @@ -3288,7 +2434,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let opaque_ty = tcx.hir().item(item_id); match opaque_ty.kind { - hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => { + hir::ItemKind::OpaqueTy(&hir::OpaqueTy { origin, .. }) => { let local_def_id = item_id.owner_id.def_id; // If this is an RPITIT and we are using the new RPITIT lowering scheme, we // generate the def_id of an associated type for the trait and return as @@ -3308,7 +2454,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let ty = self.ast_ty_to_ty_inner(qself, false, true); self.associated_path_to_ty(ast_ty.hir_id, ast_ty.span, ty, qself, segment, false) .map(|(ty, _, _)| ty) - .unwrap_or_else(|guar| tcx.ty_error(guar)) + .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) } &hir::TyKind::Path(hir::QPath::LangItem(lang_item, span, _)) => { let def_id = tcx.require_lang_item(lang_item, Some(span)); @@ -3332,7 +2478,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }; - tcx.mk_array_with_const_len(self.ast_ty_to_ty(ty), length) + Ty::new_array_with_const_len(tcx, self.ast_ty_to_ty(ty), length) } hir::TyKind::Typeof(e) => { let ty_erased = tcx.type_of(e.def_id).subst_identity(); @@ -3356,7 +2502,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // handled specially and will not descend into this routine. self.ty_infer(None, ast_ty.span) } - hir::TyKind::Err(guar) => tcx.ty_error(*guar), + hir::TyKind::Err(guar) => Ty::new_error(tcx, *guar), }; self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span); @@ -3393,7 +2539,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }); debug!("impl_trait_ty_to_ty: substs={:?}", substs); - if in_trait { tcx.mk_projection(def_id, substs) } else { tcx.mk_opaque(def_id, substs) } + if in_trait { + Ty::new_projection(tcx, def_id, substs) + } else { + Ty::new_opaque(tcx, def_id, substs) + } } pub fn ty_of_arg(&self, ty: &hir::Ty<'_>, expected_ty: Option>) -> Ty<'tcx> { @@ -3462,7 +2612,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_ty_to_ty(output) } } - hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(), + hir::FnRetTy::DefaultReturn(..) => Ty::new_unit(tcx,), }; debug!(?output_ty); @@ -3641,148 +2791,4 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } Some(r) } - - /// Make sure that we are in the condition to suggest the blanket implementation. - fn maybe_lint_blanket_trait_impl(&self, self_ty: &hir::Ty<'_>, diag: &mut Diagnostic) { - let tcx = self.tcx(); - let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; - if let hir::Node::Item(hir::Item { - kind: - hir::ItemKind::Impl(hir::Impl { - self_ty: impl_self_ty, of_trait: Some(of_trait_ref), generics, .. - }), - .. - }) = tcx.hir().get_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()) { - return; - } - let of_trait_span = of_trait_ref.path.span; - // make sure that we are not calling unwrap to abort during the compilation - let Ok(impl_trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return; }; - let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { return; }; - // check if the trait has generics, to make a correct suggestion - let param_name = generics.params.next_type_param_name(None); - - let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() { - (span, format!(", {}: {}", param_name, impl_trait_name)) - } else { - (generics.span, format!("<{}: {}>", param_name, impl_trait_name)) - }; - diag.multipart_suggestion( - format!("alternatively use a blanket \ - implementation to implement `{of_trait_name}` for \ - all types that also implement `{impl_trait_name}`"), - vec![ - (self_ty.span, param_name), - add_generic_sugg, - ], - Applicability::MaybeIncorrect, - ); - } - } - - fn maybe_lint_bare_trait(&self, self_ty: &hir::Ty<'_>, in_path: bool) { - let tcx = self.tcx(); - if let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = - self_ty.kind - { - let needs_bracket = in_path - && !tcx - .sess - .source_map() - .span_to_prev_source(self_ty.span) - .ok() - .is_some_and(|s| s.trim_end().ends_with('<')); - - let is_global = poly_trait_ref.trait_ref.path.is_global(); - - let mut sugg = Vec::from_iter([( - self_ty.span.shrink_to_lo(), - format!( - "{}dyn {}", - if needs_bracket { "<" } else { "" }, - if is_global { "(" } else { "" }, - ), - )]); - - if is_global || needs_bracket { - sugg.push(( - self_ty.span.shrink_to_hi(), - format!( - "{}{}", - if is_global { ")" } else { "" }, - if needs_bracket { ">" } else { "" }, - ), - )); - } - - if self_ty.span.edition().rust_2021() { - let msg = "trait objects must include the `dyn` keyword"; - let label = "add `dyn` keyword before this trait"; - let mut diag = - rustc_errors::struct_span_err!(tcx.sess, self_ty.span, E0782, "{}", msg); - if self_ty.span.can_be_used_for_suggestions() { - diag.multipart_suggestion_verbose( - label, - sugg, - Applicability::MachineApplicable, - ); - } - // 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); - diag.stash(self_ty.span, StashKey::TraitMissingMethod); - } else { - let msg = "trait objects without an explicit `dyn` are deprecated"; - tcx.struct_span_lint_hir( - BARE_TRAIT_OBJECTS, - self_ty.hir_id, - self_ty.span, - msg, - |lint| { - lint.multipart_suggestion_verbose( - "use `dyn`", - sugg, - Applicability::MachineApplicable, - ); - self.maybe_lint_blanket_trait_impl(&self_ty, lint); - lint - }, - ); - } - } - } -} - -pub trait InferCtxtExt<'tcx> { - fn fresh_item_substs(&self, def_id: DefId) -> SubstsRef<'tcx>; -} - -impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { - fn fresh_item_substs(&self, def_id: DefId) -> SubstsRef<'tcx> { - InternalSubsts::for_item(self.tcx, def_id, |param, _| match param.kind { - GenericParamDefKind::Lifetime => self.tcx.lifetimes.re_erased.into(), - GenericParamDefKind::Type { .. } => self - .next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::SubstitutionPlaceholder, - span: self.tcx.def_span(def_id), - }) - .into(), - GenericParamDefKind::Const { .. } => { - let span = self.tcx.def_span(def_id); - let origin = ConstVariableOrigin { - kind: ConstVariableOriginKind::SubstitutionPlaceholder, - span, - }; - self.next_const_var( - self.tcx - .type_of(param.def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"), - origin, - ) - .into() - } - }) - } } -- cgit v1.2.3