summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /compiler/rustc_hir_analysis
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_hir_analysis')
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl26
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/bounds.rs575
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs26
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/lint.rs124
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs1296
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/object_safety.rs408
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs53
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs272
-rw-r--r--compiler/rustc_hir_analysis/src/check/dropck.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs183
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs62
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs278
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/builtin.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/orphan.rs61
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs102
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs59
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs57
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs328
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs73
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs89
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs131
-rw-r--r--compiler/rustc_hir_analysis/src/constrained_generic_params.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs63
-rw-r--r--compiler/rustc_hir_analysis/src/hir_wf_check.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs17
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs81
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs34
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/explicit.rs61
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/mod.rs50
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs33
36 files changed, 2620 insertions, 2010 deletions
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 02d1dfcd1..166760166 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -99,6 +99,15 @@ hir_analysis_invalid_union_field =
hir_analysis_invalid_union_field_sugg =
wrap the field type in `ManuallyDrop<...>`
+hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl
+ .label = const parameter declared here
+
+hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetimes from an fn or impl
+ .label = lifetime declared here
+
+hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl
+ .label = type parameter declared here
+
hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
.label = lifetimes do not match {$item_kind} in trait
@@ -137,7 +146,7 @@ hir_analysis_missing_trait_item_suggestion = implement the missing item: `{$snip
hir_analysis_missing_trait_item_unstable = not all trait items implemented, missing: `{$missing_item_name}`
.note = default implementation of `{$missing_item_name}` is unstable
- .some_note = use of unstable library feature '{$feature}': {$r}
+ .some_note = use of unstable library feature '{$feature}': {$reason}
.none_note = use of unstable library feature '{$feature}'
hir_analysis_missing_type_params =
@@ -195,6 +204,13 @@ hir_analysis_return_type_notation_conflicting_bound =
hir_analysis_return_type_notation_equality_bound =
return type notation is not allowed to use type equality
+hir_analysis_return_type_notation_illegal_param_const =
+ return type notation is not allowed for functions that have const parameters
+ .label = const parameter declared here
+hir_analysis_return_type_notation_illegal_param_type =
+ return type notation is not allowed for functions that have type parameters
+ .label = type parameter declared here
+
hir_analysis_return_type_notation_missing_method =
cannot find associated function `{$assoc_name}` for `{$ty_name}`
@@ -232,6 +248,9 @@ hir_analysis_static_specialize = cannot specialize on `'static` lifetime
hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
+hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature
+ .note = this item must mention the opaque type in its signature in order to be able to register hidden types
+
hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
hir_analysis_too_large_static = extern static is too large for the current architecture
@@ -272,6 +291,11 @@ hir_analysis_unrecognized_intrinsic_function =
unrecognized intrinsic function: `{$name}`
.label = unrecognized intrinsic
+hir_analysis_unused_associated_type_bounds =
+ unnecessary associated type bound for not object safe associated type
+ .note = this associated type has a `where Self: Sized` bound. Thus, while the associated type can be specified, it cannot be used in any way, because trait objects are not `Sized`.
+ .suggestion = remove this bound
+
hir_analysis_value_of_associated_struct_already_specified =
the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified
.label = re-bound here
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
new file mode 100644
index 000000000..b13de7701
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -0,0 +1,575 @@
+use rustc_data_structures::fx::FxHashMap;
+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_span::symbol::Ident;
+use rustc_span::{ErrorGuaranteed, Span};
+use rustc_trait_selection::traits;
+
+use crate::astconv::{
+ AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter,
+};
+use crate::bounds::Bounds;
+use crate::errors::{MultipleRelaxedDefaultBounds, ValueOfAssociatedStructAlreadySpecified};
+
+impl<'tcx> dyn AstConv<'tcx> + '_ {
+ /// 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<T: Debug>
+ /// ^ ^^^^^ `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<Item = &'hir hir::GenericBound<'hir>>>(
+ &self,
+ param_ty: Ty<'tcx>,
+ ast_bounds: I,
+ bounds: &mut Bounds<'tcx>,
+ bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
+ 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<T: Bar + Baz>() { }
+ /// // ^ ^^^^^^^^^ 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<'_>],
+ filter: PredicateFilter,
+ ) -> Bounds<'tcx> {
+ let mut bounds = Bounds::default();
+
+ let only_self_bounds = match filter {
+ PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
+ OnlySelfBounds(false)
+ }
+ PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => OnlySelfBounds(true),
+ };
+
+ self.add_bounds(
+ param_ty,
+ ast_bounds.iter().filter(|bound| {
+ match filter {
+ PredicateFilter::All
+ | PredicateFilter::SelfOnly
+ | PredicateFilter::SelfAndAssociatedTypeBounds => true,
+ PredicateFilter::SelfThatDefines(assoc_name) => {
+ if let Some(trait_ref) = bound.trait_ref()
+ && let Some(trait_did) = trait_ref.trait_def_id()
+ && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name)
+ {
+ true
+ } else {
+ false
+ }
+ }
+ }
+ }),
+ &mut bounds,
+ ty::List::empty(),
+ only_self_bounds,
+ );
+ 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<Item = &'a u32>`, 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))]
+ pub(super) 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<DefId, Span>,
+ path_span: Span,
+ constness: ty::BoundConstness,
+ only_self_bounds: OnlySelfBounds,
+ polarity: ty::ImplPolarity,
+ ) -> Result<(), ErrorGuaranteed> {
+ // Given something like `U: SomeTrait<T = X>`, we want to produce a
+ // predicate like `<U as SomeTrait>::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<i32> { }
+ // trait SuperTrait<A> { type T; }
+ //
+ // ... B: SubTrait<T = foo> ...
+ // ```
+ //
+ // We want to produce `<B as SuperTrait<i32>>::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 {
+ 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.
+ 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 {
+ ty::GenericParamDefKind::Lifetime => ty::Region::new_late_bound(
+ tcx,
+ ty::INNERMOST,
+ ty::BoundRegion {
+ var: ty::BoundVar::from_usize(num_bound_vars),
+ kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name),
+ },
+ )
+ .into(),
+ ty::GenericParamDefKind::Type { .. } => {
+ if !emitted_bad_param_err {
+ tcx.sess.emit_err(
+ crate::errors::ReturnTypeNotationIllegalParam::Type {
+ span: path_span,
+ param_span: tcx.def_span(param.def_id),
+ },
+ );
+ emitted_bad_param_err = true;
+ }
+ Ty::new_bound(
+ tcx,
+ ty::INNERMOST,
+ ty::BoundTy {
+ var: ty::BoundVar::from_usize(num_bound_vars),
+ kind: ty::BoundTyKind::Param(param.def_id, param.name),
+ },
+ )
+ .into()
+ }
+ ty::GenericParamDefKind::Const { .. } => {
+ if !emitted_bad_param_err {
+ tcx.sess.emit_err(
+ crate::errors::ReturnTypeNotationIllegalParam::Const {
+ span: path_span,
+ param_span: tcx.def_span(param.def_id),
+ },
+ );
+ emitted_bad_param_err = true;
+ }
+ let ty = tcx
+ .type_of(param.def_id)
+ .no_bound_vars()
+ .expect("ct params cannot have early bound vars");
+ ty::Const::new_bound(
+ tcx,
+ 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.is_impl_trait_in_trait(alias_ty.def_id)
+ {
+ 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::bind(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> <T as Iterator>::Item = &'a str // <-- 'a is bad
+ // for<'a> <T as FnMut<(&'a u32,)>>::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<F: for<'a> 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<Item = u32>` this to
+ // the "projection predicate" for:
+ //
+ // `<T as Iterator>::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 => Ty::new_error(tcx, reported).into(),
+ hir::def::DefKind::AssocConst => ty::Const::new_error(
+ tcx,
+ reported,
+ tcx.type_of(assoc_item_def_id)
+ .subst(tcx, projection_ty.skip_binder().substs),
+ )
+ .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<Item: Debug>` to
+ //
+ // `<T as Iterator>::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 = Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
+ self.add_bounds(
+ param_ty,
+ ast_bounds.iter(),
+ bounds,
+ projection_ty.bound_vars(),
+ only_self_bounds,
+ );
+ }
+ }
+ }
+ Ok(())
+ }
+}
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index 7b922f5d5..ddf99853b 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -122,9 +122,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let all_candidate_names: Vec<_> = all_candidates()
.flat_map(|r| self.tcx().associated_items(r.def_id()).in_definition_order())
- .filter_map(
- |item| if item.kind == ty::AssocKind::Type { Some(item.name) } else { None },
- )
+ .filter_map(|item| {
+ if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type {
+ Some(item.name)
+ } else {
+ None
+ }
+ })
.collect();
if let (Some(suggested_name), true) = (
@@ -159,9 +163,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
.flat_map(|trait_def_id| {
self.tcx().associated_items(*trait_def_id).in_definition_order()
})
- .filter_map(
- |item| if item.kind == ty::AssocKind::Type { Some(item.name) } else { None },
- )
+ .filter_map(|item| {
+ if item.opt_rpitit_info.is_none() && item.kind == ty::AssocKind::Type {
+ Some(item.name)
+ } else {
+ None
+ }
+ })
.collect();
if let (Some(suggested_name), true) = (
@@ -343,13 +351,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let format_pred = |pred: ty::Predicate<'tcx>| {
let bound_predicate = pred.kind();
match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
let pred = bound_predicate.rebind(pred);
// `<Foo as Iterator>::Item = String`.
let projection_ty = pred.skip_binder().projection_ty;
let substs_with_infer_self = tcx.mk_substs_from_iter(
- std::iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into())
+ std::iter::once(Ty::new_var(tcx, ty::TyVid::from_u32(0)).into())
.chain(projection_ty.substs.iter().skip(1)),
);
@@ -364,7 +372,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
Some((obligation, projection_ty.self_ty()))
}
- ty::PredicateKind::Clause(ty::Clause::Trait(poly_trait_ref)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => {
let p = poly_trait_ref.trait_ref;
let self_ty = p.self_ty();
let path = p.print_only_trait_path();
diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs
new file mode 100644
index 000000000..05a3ab63d
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs
@@ -0,0 +1,124 @@
+use rustc_ast::TraitObjectSyntax;
+use rustc_errors::{Diagnostic, StashKey};
+use rustc_hir as hir;
+use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability};
+use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
+
+use super::AstConv;
+
+impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
+ /// Make sure that we are in the condition to suggest the blanket implementation.
+ pub(super) 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,
+ );
+ }
+ }
+
+ pub(super) 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
+ },
+ );
+ }
+ }
+ }
+}
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<A: B>`, this would expand to `Self: Tr`
+ /// and `<Self as Tr>::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<T: Debug>
- /// ^ ^^^^^ `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<Item = &'hir hir::GenericBound<'hir>>>(
- &self,
- param_ty: Ty<'tcx>,
- ast_bounds: I,
- bounds: &mut Bounds<'tcx>,
- bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
- 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<T: Bar + Baz>() { }
- /// // ^ ^^^^^^^^^ 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<Item = &'a u32>`, 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<DefId, Span>,
- path_span: Span,
- constness: ty::BoundConstness,
- only_self_bounds: OnlySelfBounds,
- polarity: ty::ImplPolarity,
- ) -> Result<(), ErrorGuaranteed> {
- // Given something like `U: SomeTrait<T = X>`, we want to produce a
- // predicate like `<U as SomeTrait>::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<i32> { }
- // trait SuperTrait<A> { type T; }
- //
- // ... B: SubTrait<T = foo> ...
- // ```
- //
- // We want to produce `<B as SuperTrait<i32>>::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> <T as Iterator>::Item = &'a str // <-- 'a is bad
- // for<'a> <T as FnMut<(&'a u32,)>>::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<F: for<'a> 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<Item = u32>` this to
- // the "projection predicate" for:
- //
- // `<T as Iterator>::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<Item: Debug>` to
- //
- // `<T as Iterator>::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 = &regular_traits[0];
- let additional_trait = &regular_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::<Vec<_>>()
- .join(" + "),
- ));
- err.note(
- "auto-traits like `Send` and `Sync` are traits that have special properties; \
- for more information on them, visit \
- <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
- );
- 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 &regular_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<Span, BTreeSet<DefId>> = 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() -> <Self as MyTrait>::MyOutput {
- // type MyOutput;
- // }
- // ```
- //
- // Here, the user could theoretically write `dyn MyTrait<Output = X>`,
- // but actually supporting that would "expand" to an infinitely-long type
- // `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`.
- //
- // Instead, we force the user to write
- // `dyn MyTrait<MyOutput = X, Output = X>`, 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::<SmallVec<[_; 8]>>();
- 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<Option<(Ty<'tcx>, 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<TyCtxt<'tcx>> 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>,
+ ) -> <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),
+ }
+ }
+ }
+
+ 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>>) -> 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()
- }
- })
- }
}
diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
new file mode 100644
index 000000000..9227ee934
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
@@ -0,0 +1,408 @@
+use crate::astconv::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds};
+use crate::bounds::Bounds;
+use crate::errors::TraitObjectDeclaredWithNoTraits;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_errors::struct_span_err;
+use rustc_hir as hir;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::DefId;
+use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
+use rustc_middle::ty::{self, Ty};
+use rustc_middle::ty::{DynKind, ToPredicate};
+use rustc_span::Span;
+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;
+
+impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
+ pub(super) fn conv_object_ty_poly_trait_ref(
+ &self,
+ span: Span,
+ hir_id: hir::HirId,
+ 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.clauses() {
+ let bound_pred = pred.kind();
+ match bound_pred.skip_binder() {
+ ty::ClauseKind::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::ClauseKind::Projection(proj) => {
+ projection_bounds.push((bound_pred.rebind(proj), span));
+ }
+ ty::ClauseKind::TypeOutlives(_) => {
+ // Do nothing, we deal with regions separately
+ }
+ ty::ClauseKind::RegionOutlives(_)
+ | ty::ClauseKind::ConstArgHasType(..)
+ | ty::ClauseKind::WellFormed(_)
+ | ty::ClauseKind::ConstEvaluatable(_) => {
+ 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 = &regular_traits[0];
+ let additional_trait = &regular_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::<Vec<_>>()
+ .join(" + "),
+ ));
+ err.note(
+ "auto-traits like `Send` and `Sync` are traits that have special properties; \
+ for more information on them, visit \
+ <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
+ );
+ 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 Ty::new_error(tcx, 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 &regular_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 Ty::new_error(tcx, reported);
+ }
+ }
+
+ // Use a `BTreeSet` to keep output in a more consistent order.
+ let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = 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::ClauseKind::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| item.opt_rpitit_info.is_none())
+ .map(|item| item.def_id),
+ );
+ }
+ ty::PredicateKind::Clause(ty::ClauseKind::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() -> <Self as MyTrait>::MyOutput {
+ // type MyOutput;
+ // }
+ // ```
+ //
+ // Here, the user could theoretically write `dyn MyTrait<Output = X>`,
+ // but actually supporting that would "expand" to an infinitely-long type
+ // `fix $ τ → dyn MyTrait<MyOutput = X, Output = <τ as MyTrait>::MyOutput`.
+ //
+ // Instead, we force the user to write
+ // `dyn MyTrait<MyOutput = X, Output = X>`, 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));
+ }
+ }
+ _ => (),
+ }
+ }
+ }
+
+ // `dyn Trait<Assoc = Foo>` desugars to (not Rust syntax) `dyn Trait where <Self as Trait>::Assoc = Foo`.
+ // So every `Projection` clause is an `Assoc = Foo` bound. `associated_types` contains all associated
+ // types's `DefId`, so the following loop removes all the `DefIds` of the associated types that have a
+ // corresponding `Projection` clause
+ for def_ids in associated_types.values_mut() {
+ for (projection_bound, span) in &projection_bounds {
+ let def_id = projection_bound.projection_def_id();
+ def_ids.remove(&def_id);
+ if tcx.generics_require_sized_self(def_id) {
+ tcx.emit_spanned_lint(
+ UNUSED_ASSOCIATED_TYPE_BOUNDS,
+ hir_id,
+ *span,
+ crate::errors::UnusedAssociatedTypeBounds { span: *span },
+ );
+ }
+ }
+ // If the associated type has a `where Self: Sized` bound, we do not need to constrain the associated
+ // type in the `dyn Trait`.
+ def_ids.retain(|def_id| !tcx.generics_require_sized_self(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 Ty::new_misc_error(tcx).into();
+ } else if arg.walk().any(|arg| arg == dummy_self.into()) {
+ references_self = true;
+ return Ty::new_misc_error(tcx).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,
+ );
+
+ 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 Ty::new_error(tcx, 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::<SmallVec<[_; 8]>>();
+ 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)
+ } 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()
+ };
+ ty::Region::new_error(tcx, e)
+ })
+ }
+ })
+ };
+ debug!("region_bound: {:?}", region_bound);
+
+ let ty = Ty::new_dynamic(tcx, existential_predicates, region_bound, representation);
+ debug!("trait_object_type: {:?}", ty);
+ ty
+ }
+}
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index d6d1498d7..c07ac35cb 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -73,7 +73,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
// NOTE: we may still need to normalize the built-in deref in case
// we have some type like `&<Ty as Trait>::Assoc`, since users of
// autoderef expect this type to have been structurally normalized.
- if self.infcx.tcx.trait_solver_next()
+ if self.infcx.next_trait_solver()
&& let ty::Alias(ty::Projection, _) = ty.kind()
{
let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
@@ -148,8 +148,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
return None;
}
- let (normalized_ty, obligations) =
- self.structurally_normalize(tcx.mk_projection(tcx.lang_items().deref_target()?, [ty]))?;
+ let (normalized_ty, obligations) = self.structurally_normalize(Ty::new_projection(
+ tcx,
+ tcx.lang_items().deref_target()?,
+ [ty],
+ ))?;
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
self.state.obligations.extend(obligations);
@@ -161,8 +164,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
&self,
ty: Ty<'tcx>,
) -> Option<(Ty<'tcx>, Vec<traits::PredicateObligation<'tcx>>)> {
- let tcx = self.infcx.tcx;
- let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new_in_snapshot(tcx);
+ let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(self.infcx);
let cause = traits::ObligationCause::misc(self.span, self.body_id);
let normalized_ty = match self
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index 686066abb..531100e1f 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -23,7 +23,7 @@ use rustc_span::Span;
/// include the self type (e.g., `trait_bounds`) but in others we do not
#[derive(Default, PartialEq, Eq, Clone, Debug)]
pub struct Bounds<'tcx> {
- pub predicates: Vec<(ty::Predicate<'tcx>, Span)>,
+ pub clauses: Vec<(ty::Clause<'tcx>, Span)>,
}
impl<'tcx> Bounds<'tcx> {
@@ -33,7 +33,8 @@ impl<'tcx> Bounds<'tcx> {
region: ty::PolyTypeOutlivesPredicate<'tcx>,
span: Span,
) {
- self.predicates.push((region.to_predicate(tcx), span));
+ self.clauses
+ .push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).to_predicate(tcx), span));
}
pub fn push_trait_bound(
@@ -44,9 +45,11 @@ impl<'tcx> Bounds<'tcx> {
constness: ty::BoundConstness,
polarity: ty::ImplPolarity,
) {
- self.predicates.push((
+ self.clauses.push((
trait_ref
- .map_bound(|trait_ref| ty::TraitPredicate { trait_ref, constness, polarity })
+ .map_bound(|trait_ref| {
+ ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, constness, polarity })
+ })
.to_predicate(tcx),
span,
));
@@ -58,17 +61,20 @@ impl<'tcx> Bounds<'tcx> {
projection: ty::PolyProjectionPredicate<'tcx>,
span: Span,
) {
- self.predicates.push((projection.to_predicate(tcx), span));
+ self.clauses.push((
+ projection.map_bound(|proj| ty::ClauseKind::Projection(proj)).to_predicate(tcx),
+ span,
+ ));
}
pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) {
let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]);
// Preferable to put this obligation first, since we report better errors for sized ambiguity.
- self.predicates.insert(0, (trait_ref.without_const().to_predicate(tcx), span));
+ self.clauses.insert(0, (trait_ref.to_predicate(tcx), span));
}
- pub fn predicates(&self) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> + '_ {
- self.predicates.iter().cloned()
+ pub fn clauses(&self) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_ {
+ self.clauses.iter().cloned()
}
}
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 3b2c052e8..120545c8e 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -177,7 +177,7 @@ 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, e.to_string());
+ tcx.sess.delay_span_bug(span, format!("{e:?}"));
return;
}
};
@@ -224,7 +224,8 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() {
return;
}
- 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 use `Self` or `T::Foo` projections that would result
@@ -299,7 +300,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
}
}
- if let ItemKind::OpaqueTy(hir::OpaqueTy {
+ if let ItemKind::OpaqueTy(&hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
in_trait,
..
@@ -307,9 +308,9 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
{
let substs = InternalSubsts::identity_for_item(tcx, def_id);
let opaque_identity_ty = if in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
- tcx.mk_projection(def_id.to_def_id(), substs)
+ Ty::new_projection(tcx, def_id.to_def_id(), substs)
} else {
- tcx.mk_opaque(def_id.to_def_id(), substs)
+ Ty::new_opaque(tcx, def_id.to_def_id(), substs)
};
let mut visitor = ProhibitOpaqueVisitor {
opaque_identity_ty,
@@ -395,7 +396,7 @@ fn check_opaque_meets_bounds<'tcx>(
def_id: LocalDefId,
span: Span,
origin: &hir::OpaqueTyOrigin,
-) {
+) -> Result<(), ErrorGuaranteed> {
let defining_use_anchor = match *origin {
hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
hir::OpaqueTyOrigin::TyAlias { .. } => tcx.impl_trait_parent(def_id),
@@ -409,7 +410,7 @@ fn check_opaque_meets_bounds<'tcx>(
let ocx = ObligationCtxt::new(&infcx);
let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
- let opaque_ty = tcx.mk_opaque(def_id.to_def_id(), substs);
+ let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), substs);
// `ReErased` regions appear in the "parent_substs" of closures/generators.
// We're ignoring them here and replacing them with fresh region variables.
@@ -429,24 +430,26 @@ fn check_opaque_meets_bounds<'tcx>(
Ok(()) => {}
Err(ty_err) => {
let ty_err = ty_err.to_string(tcx);
- tcx.sess.delay_span_bug(
+ return Err(tcx.sess.delay_span_bug(
span,
format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
- );
+ ));
}
}
// Additionally require the hidden type to be well-formed with only the generics of the opaque type.
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
// hidden type is well formed even without those bounds.
- let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_ty.into()));
+ let predicate =
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(hidden_ty.into())));
ocx.register_obligation(Obligation::new(tcx, misc_cause, param_env, predicate));
// Check that all obligations are satisfied by the implementation's
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- infcx.err_ctxt().report_fulfillment_errors(&errors);
+ let guar = infcx.err_ctxt().report_fulfillment_errors(&errors);
+ return Err(guar);
}
match origin {
// Checked when type checking the function containing them.
@@ -460,14 +463,15 @@ fn check_opaque_meets_bounds<'tcx>(
if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {}
// Can have different predicates to their defining use
hir::OpaqueTyOrigin::TyAlias { .. } => {
- let wf_tys = ocx.assumed_wf_types(param_env, span, def_id);
+ let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, def_id)?;
let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys);
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
- let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env);
+ ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
}
}
// Clean up after ourselves
let _ = infcx.take_opaque_types();
+ Ok(())
}
fn is_enum_of_nonnullable_ptr<'tcx>(
@@ -562,8 +566,8 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
check_union(tcx, id.owner_id.def_id);
}
DefKind::OpaqueTy => {
- let opaque = tcx.hir().expect_item(id.owner_id.def_id).expect_opaque_ty();
- if let hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = opaque.origin
+ 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::TraitFn::Required(..)) = trait_item.expect_fn()
{
@@ -704,7 +708,7 @@ pub(super) fn check_specialization_validity<'tcx>(
// grandparent. In that case, if parent is a `default impl`, inherited items use the
// "defaultness" from the grandparent, else they are final.
None => {
- if tcx.impl_defaultness(parent_impl.def_id()).is_default() {
+ if tcx.defaultness(parent_impl.def_id()).is_default() {
None
} else {
Some(Err(parent_impl.def_id()))
@@ -718,7 +722,14 @@ pub(super) fn check_specialization_validity<'tcx>(
let result = opt_result.unwrap_or(Ok(()));
if let Err(parent_impl) = result {
- report_forbidden_specialization(tcx, impl_item, parent_impl);
+ if !tcx.is_impl_trait_in_trait(impl_item) {
+ report_forbidden_specialization(tcx, impl_item, parent_impl);
+ } else {
+ tcx.sess.delay_span_bug(
+ DUMMY_SP,
+ format!("parent item: {:?} not marked as default", parent_impl),
+ );
+ }
}
}
@@ -803,7 +814,7 @@ fn check_impl_items_against_trait<'tcx>(
.as_ref()
.is_some_and(|node_item| node_item.item.defaultness(tcx).has_value());
- if !is_implemented && tcx.impl_defaultness(impl_id).is_final() {
+ if !is_implemented && tcx.defaultness(impl_id).is_final() {
missing_items.push(tcx.associated_item(trait_item_id));
}
@@ -1481,7 +1492,9 @@ fn opaque_type_cycle_error(
}
for closure_def_id in visitor.closures {
- let Some(closure_local_did) = closure_def_id.as_local() else { continue; };
+ let Some(closure_local_did) = closure_def_id.as_local() else {
+ continue;
+ };
let typeck_results = tcx.typeck(closure_local_did);
let mut label_match = |ty: Ty<'_>, span| {
@@ -1549,7 +1562,7 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
.with_opaque_type_inference(DefiningAnchor::Bind(def_id))
.build();
- let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
+ let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx);
for (predicate, cause) in generator_interior_predicates {
let obligation = Obligation::new(tcx, cause.clone(), param_env, *predicate);
fulfillment_cx.register_predicate_obligation(&infcx, obligation);
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 8bf1e0e84..22e576e34 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -19,12 +19,13 @@ use rustc_middle::ty::{
self, InternalSubsts, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
use rustc_middle::ty::{GenericParamDefKind, ToPredicate, TyCtxt};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{
self, ObligationCause, ObligationCauseCode, ObligationCtxt, Reveal,
};
+use std::borrow::Cow;
use std::iter;
/// Checks that a method from an impl conforms to the signature of
@@ -44,12 +45,7 @@ pub(super) fn compare_impl_method<'tcx>(
debug!("compare_impl_method(impl_trait_ref={:?})", impl_trait_ref);
let _: Result<_, ErrorGuaranteed> = try {
- compare_self_type(tcx, impl_m, trait_m, impl_trait_ref)?;
- compare_number_of_generics(tcx, impl_m, trait_m, false)?;
- compare_generic_param_kinds(tcx, impl_m, trait_m, false)?;
- compare_number_of_method_arguments(tcx, impl_m, trait_m)?;
- compare_synthetic_generics(tcx, impl_m, trait_m)?;
- compare_asyncness(tcx, impl_m, trait_m)?;
+ check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, false)?;
compare_method_predicate_entailment(
tcx,
impl_m,
@@ -60,6 +56,26 @@ pub(super) fn compare_impl_method<'tcx>(
};
}
+/// Checks a bunch of different properties of the impl/trait methods for
+/// compatibility, such as asyncness, number of argument, self receiver kind,
+/// and number of early- and late-bound generics.
+fn check_method_is_structurally_compatible<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ impl_m: ty::AssocItem,
+ trait_m: ty::AssocItem,
+ impl_trait_ref: ty::TraitRef<'tcx>,
+ delay: bool,
+) -> Result<(), ErrorGuaranteed> {
+ compare_self_type(tcx, impl_m, trait_m, impl_trait_ref, delay)?;
+ compare_number_of_generics(tcx, impl_m, trait_m, delay)?;
+ compare_generic_param_kinds(tcx, impl_m, trait_m, delay)?;
+ compare_number_of_method_arguments(tcx, impl_m, trait_m, delay)?;
+ compare_synthetic_generics(tcx, impl_m, trait_m, delay)?;
+ compare_asyncness(tcx, impl_m, trait_m, delay)?;
+ check_region_bounds_on_impl_item(tcx, impl_m, trait_m, delay)?;
+ Ok(())
+}
+
/// This function is best explained by example. Consider a trait with it's implementation:
///
/// ```rust
@@ -176,9 +192,6 @@ fn compare_method_predicate_entailment<'tcx>(
let impl_m_predicates = tcx.predicates_of(impl_m.def_id);
let trait_m_predicates = tcx.predicates_of(trait_m.def_id);
- // Check region bounds.
- check_region_bounds_on_impl_item(tcx, impl_m, trait_m, false)?;
-
// Create obligations for each predicate declared by the impl
// definition in the context of the trait's parameter
// environment. We can't just use `impl_env.caller_bounds`,
@@ -207,7 +220,7 @@ fn compare_method_predicate_entailment<'tcx>(
// the new hybrid bounds we computed.
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_def_id);
let param_env = ty::ParamEnv::new(
- tcx.mk_predicates(&hybrid_preds.predicates),
+ tcx.mk_clauses(&hybrid_preds.predicates),
Reveal::UserFacing,
hir::Constness::NotConst,
);
@@ -258,7 +271,7 @@ fn compare_method_predicate_entailment<'tcx>(
infer::HigherRankedType,
tcx.fn_sig(impl_m.def_id).subst_identity(),
);
- let unnormalized_impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(unnormalized_impl_sig));
+ let unnormalized_impl_fty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(unnormalized_impl_sig));
let norm_cause = ObligationCause::misc(impl_m_span, impl_m_def_id);
let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig);
@@ -275,7 +288,7 @@ fn compare_method_predicate_entailment<'tcx>(
// We also have to add the normalized trait signature
// as we don't normalize during implied bounds computation.
wf_tys.extend(trait_sig.inputs_and_output.iter());
- let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
+ let trait_fty = Ty::new_fn_ptr(tcx, ty::Binder::dummy(trait_sig));
debug!("compare_impl_method: trait_fty={:?}", trait_fty);
@@ -301,14 +314,16 @@ fn compare_method_predicate_entailment<'tcx>(
return Err(emitted);
}
- if check_implied_wf == CheckImpliedWfMode::Check {
+ if check_implied_wf == CheckImpliedWfMode::Check && !(impl_sig, trait_sig).references_error() {
// We need to check that the impl's args are well-formed given
// the hybrid param-env (impl + trait method where-clauses).
ocx.register_obligation(traits::Obligation::new(
infcx.tcx,
ObligationCause::dummy(),
param_env,
- ty::Binder::dummy(ty::PredicateKind::WellFormed(unnormalized_impl_fty.into())),
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
+ unnormalized_impl_fty.into(),
+ ))),
));
}
@@ -471,7 +486,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 {
- self.tcx.mk_re_free(
+ ty::Region::new_free(
+ self.tcx,
fr.scope,
self.mapping.get(&fr.bound_region).copied().unwrap_or(fr.bound_region),
)
@@ -532,6 +548,7 @@ fn compare_asyncness<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m: ty::AssocItem,
trait_m: ty::AssocItem,
+ delay: bool,
) -> Result<(), ErrorGuaranteed> {
if tcx.asyncness(trait_m.def_id) == hir::IsAsync::Async {
match tcx.fn_sig(impl_m.def_id).skip_binder().skip_binder().output().kind() {
@@ -542,11 +559,14 @@ fn compare_asyncness<'tcx>(
// We don't know if it's ok, but at least it's already an error.
}
_ => {
- return Err(tcx.sess.emit_err(crate::errors::AsyncTraitImplShouldBeAsync {
- span: tcx.def_span(impl_m.def_id),
- method_name: trait_m.name,
- trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
- }));
+ return Err(tcx
+ .sess
+ .create_err(crate::errors::AsyncTraitImplShouldBeAsync {
+ span: tcx.def_span(impl_m.def_id),
+ method_name: trait_m.name,
+ trait_item_span: tcx.hir().span_if_local(trait_m.def_id),
+ })
+ .emit_unless(delay));
}
};
}
@@ -600,9 +620,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
// First, check a few of the same things as `compare_impl_method`,
// just so we don't ICE during substitution later.
- compare_number_of_generics(tcx, impl_m, trait_m, true)?;
- compare_generic_param_kinds(tcx, impl_m, trait_m, true)?;
- check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?;
+ check_method_is_structurally_compatible(tcx, impl_m, trait_m, impl_trait_ref, true)?;
let trait_to_impl_substs = impl_trait_ref.substs;
@@ -633,11 +651,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let impl_sig = ocx.normalize(
&norm_cause,
param_env,
- infcx.instantiate_binder_with_fresh_vars(
- return_span,
- infer::HigherRankedType,
- tcx.fn_sig(impl_m.def_id).subst_identity(),
- ),
+ tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(impl_m.def_id).subst_identity()),
);
impl_sig.error_reported()?;
let impl_return_ty = impl_sig.output();
@@ -647,18 +661,21 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
// them with inference variables.
// We will use these inference variables to collect the hidden types of RPITITs.
let mut collector = ImplTraitInTraitCollector::new(&ocx, return_span, param_env, impl_m_def_id);
- let unnormalized_trait_sig = tcx
- .liberate_late_bound_regions(
- impl_m.def_id,
+ let unnormalized_trait_sig = infcx
+ .instantiate_binder_with_fresh_vars(
+ return_span,
+ infer::HigherRankedType,
tcx.fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs),
)
.fold_with(&mut collector);
- debug_assert_ne!(
- collector.types.len(),
- 0,
- "expect >1 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`"
- );
+ if !unnormalized_trait_sig.output().references_error() {
+ debug_assert_ne!(
+ collector.types.len(),
+ 0,
+ "expect >1 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`"
+ );
+ }
let trait_sig = ocx.normalize(&norm_cause, param_env, unnormalized_trait_sig);
trait_sig.error_reported()?;
@@ -684,7 +701,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
&cause,
hir.get_if_local(impl_m.def_id)
.and_then(|node| node.fn_decl())
- .map(|decl| (decl.output.span(), "return type in trait".to_owned())),
+ .map(|decl| (decl.output.span(), Cow::from("return type in trait"))),
Some(infer::ValuePairs::Terms(ExpectedFound {
expected: trait_return_ty.into(),
found: impl_return_ty.into(),
@@ -742,15 +759,17 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
let mut collected_tys = FxHashMap::default();
for (def_id, (ty, substs)) in collected_types {
- match infcx.fully_resolve(ty) {
- Ok(ty) => {
+ match infcx.fully_resolve((ty, substs)) {
+ Ok((ty, substs)) => {
// `ty` contains free regions that we created earlier while liberating the
// trait fn signature. However, projection normalization expects `ty` to
// contains `def_id`'s early-bound regions.
let id_substs = InternalSubsts::identity_for_item(tcx, def_id);
debug!(?id_substs, ?substs);
- let map: FxHashMap<ty::GenericArg<'tcx>, ty::GenericArg<'tcx>> =
- std::iter::zip(substs, id_substs).collect();
+ let map: FxHashMap<_, _> = std::iter::zip(substs, id_substs)
+ .skip(tcx.generics_of(trait_m.def_id).count())
+ .filter_map(|(a, b)| Some((a.as_region()?, b.as_region()?)))
+ .collect();
debug!(?map);
// NOTE(compiler-errors): RPITITs, like all other RPITs, have early-bound
@@ -775,33 +794,27 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
// same generics.
let num_trait_substs = trait_to_impl_substs.len();
let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len();
- let ty = tcx.fold_regions(ty, |region, _| {
- match region.kind() {
- // Remap all free regions, which correspond to late-bound regions in the function.
- ty::ReFree(_) => {}
- // Remap early-bound regions as long as they don't come from the `impl` itself.
- ty::ReEarlyBound(ebr) if tcx.parent(ebr.def_id) != impl_m.container_id(tcx) => {}
- _ => return region,
- }
- let Some(ty::ReEarlyBound(e)) = map.get(&region.into()).map(|r| r.expect_region().kind())
- else {
- return tcx.mk_re_error_with_message(return_span, "expected ReFree to map to ReEarlyBound")
- };
- tcx.mk_re_early_bound(ty::EarlyBoundRegion {
- def_id: e.def_id,
- name: e.name,
- index: (e.index as usize - num_trait_substs + num_impl_substs) as u32,
- })
- });
- debug!(%ty);
- collected_tys.insert(def_id, ty::EarlyBinder(ty));
+ let ty = match ty.try_fold_with(&mut RemapHiddenTyRegions {
+ tcx,
+ map,
+ num_trait_substs,
+ num_impl_substs,
+ def_id,
+ impl_def_id: impl_m.container_id(tcx),
+ ty,
+ return_span,
+ }) {
+ Ok(ty) => ty,
+ Err(guar) => Ty::new_error(tcx, guar),
+ };
+ collected_tys.insert(def_id, ty::EarlyBinder::bind(ty));
}
Err(err) => {
let reported = tcx.sess.delay_span_bug(
return_span,
format!("could not fully resolve: {ty} => {err:?}"),
);
- collected_tys.insert(def_id, ty::EarlyBinder(tcx.ty_error(reported)));
+ collected_tys.insert(def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, reported)));
}
}
}
@@ -877,6 +890,97 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ImplTraitInTraitCollector<'_, 'tcx> {
}
}
+struct RemapHiddenTyRegions<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ map: FxHashMap<ty::Region<'tcx>, ty::Region<'tcx>>,
+ num_trait_substs: usize,
+ num_impl_substs: usize,
+ def_id: DefId,
+ impl_def_id: DefId,
+ ty: Ty<'tcx>,
+ return_span: Span,
+}
+
+impl<'tcx> ty::FallibleTypeFolder<TyCtxt<'tcx>> for RemapHiddenTyRegions<'tcx> {
+ type Error = ErrorGuaranteed;
+
+ fn interner(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+
+ fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
+ if let ty::Alias(ty::Opaque, ty::AliasTy { substs, def_id, .. }) = *t.kind() {
+ let mut mapped_substs = Vec::with_capacity(substs.len());
+ for (arg, v) in std::iter::zip(substs, self.tcx.variances_of(def_id)) {
+ mapped_substs.push(match (arg.unpack(), v) {
+ // Skip uncaptured opaque substs
+ (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => arg,
+ _ => arg.try_fold_with(self)?,
+ });
+ }
+ Ok(Ty::new_opaque(self.tcx, def_id, self.tcx.mk_substs(&mapped_substs)))
+ } else {
+ t.try_super_fold_with(self)
+ }
+ }
+
+ fn try_fold_region(
+ &mut self,
+ 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 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 => {}
+ _ => return Ok(region),
+ }
+
+ let e = if let Some(region) = self.map.get(&region) {
+ if let ty::ReEarlyBound(e) = region.kind() { e } else { bug!() }
+ } else {
+ let guar = match region.kind() {
+ ty::ReEarlyBound(ty::EarlyBoundRegion { def_id, .. })
+ | ty::ReFree(ty::FreeRegion {
+ bound_region: ty::BoundRegionKind::BrNamed(def_id, _),
+ ..
+ }) => {
+ let return_span = if let ty::Alias(ty::Opaque, opaque_ty) = self.ty.kind() {
+ self.tcx.def_span(opaque_ty.def_id)
+ } else {
+ self.return_span
+ };
+ self.tcx
+ .sess
+ .struct_span_err(
+ return_span,
+ "return type captures more lifetimes than trait definition",
+ )
+ .span_label(self.tcx.def_span(def_id), "this lifetime was captured")
+ .span_note(
+ self.tcx.def_span(self.def_id),
+ "hidden type must only reference lifetimes captured by this impl trait",
+ )
+ .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"),
+ };
+ return Err(guar);
+ };
+
+ Ok(ty::Region::new_early_bound(
+ self.tcx,
+ ty::EarlyBoundRegion {
+ def_id: e.def_id,
+ name: e.name,
+ index: (e.index as usize - self.num_trait_substs + self.num_impl_substs) as u32,
+ },
+ ))
+ }
+}
+
fn report_trait_method_mismatch<'tcx>(
infcx: &InferCtxt<'tcx>,
mut cause: ObligationCause<'tcx>,
@@ -901,7 +1005,7 @@ fn report_trait_method_mismatch<'tcx>(
if trait_m.fn_has_self_parameter =>
{
let ty = trait_sig.inputs()[0];
- let sugg = match ExplicitSelf::determine(ty, |_| ty == impl_trait_ref.self_ty()) {
+ let sugg = match ExplicitSelf::determine(ty, |ty| ty == impl_trait_ref.self_ty()) {
ExplicitSelf::ByValue => "self".to_owned(),
ExplicitSelf::ByReference(_, hir::Mutability::Not) => "&self".to_owned(),
ExplicitSelf::ByReference(_, hir::Mutability::Mut) => "&mut self".to_owned(),
@@ -963,7 +1067,7 @@ fn report_trait_method_mismatch<'tcx>(
infcx.err_ctxt().note_type_err(
&mut diag,
&cause,
- trait_err_span.map(|sp| (sp, "type in trait".to_owned())),
+ trait_err_span.map(|sp| (sp, Cow::from("type in trait"))),
Some(infer::ValuePairs::Sigs(ExpectedFound { expected: trait_sig, found: impl_sig })),
terr,
false,
@@ -1095,6 +1199,7 @@ fn compare_self_type<'tcx>(
impl_m: ty::AssocItem,
trait_m: ty::AssocItem,
impl_trait_ref: ty::TraitRef<'tcx>,
+ delay: bool,
) -> Result<(), ErrorGuaranteed> {
// Try to give more informative error messages about self typing
// mismatches. Note that any mismatch will also be detected
@@ -1143,7 +1248,7 @@ fn compare_self_type<'tcx>(
} else {
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
}
- return Err(err.emit());
+ return Err(err.emit_unless(delay));
}
(true, false) => {
@@ -1164,7 +1269,7 @@ fn compare_self_type<'tcx>(
err.note_trait_signature(trait_m.name, trait_m.signature(tcx));
}
- return Err(err.emit());
+ return Err(err.emit_unless(delay));
}
}
@@ -1214,7 +1319,7 @@ fn compare_number_of_generics<'tcx>(
// has mismatched type or const generic arguments, then the method that it's
// 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 tcx.opt_rpitit_info(trait_.def_id).is_some() {
+ if trait_.opt_rpitit_info.is_some() {
return Err(tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP,
"errors comparing numbers of generics of trait/impl functions were not emitted",
@@ -1350,6 +1455,7 @@ fn compare_number_of_method_arguments<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m: ty::AssocItem,
trait_m: ty::AssocItem,
+ delay: bool,
) -> Result<(), ErrorGuaranteed> {
let impl_m_fty = tcx.fn_sig(impl_m.def_id);
let trait_m_fty = tcx.fn_sig(trait_m.def_id);
@@ -1420,7 +1526,7 @@ fn compare_number_of_method_arguments<'tcx>(
),
);
- return Err(err.emit());
+ return Err(err.emit_unless(delay));
}
Ok(())
@@ -1430,6 +1536,7 @@ fn compare_synthetic_generics<'tcx>(
tcx: TyCtxt<'tcx>,
impl_m: ty::AssocItem,
trait_m: ty::AssocItem,
+ delay: bool,
) -> Result<(), ErrorGuaranteed> {
// FIXME(chrisvittal) Clean up this function, list of FIXME items:
// 1. Better messages for the span labels
@@ -1549,7 +1656,7 @@ fn compare_synthetic_generics<'tcx>(
}
_ => unreachable!(),
}
- error_found = Some(err.emit());
+ error_found = Some(err.emit_unless(delay));
}
}
if let Some(reported) = error_found { Err(reported) } else { Ok(()) }
@@ -1731,7 +1838,7 @@ pub(super) fn compare_impl_const_raw(
infcx.err_ctxt().note_type_err(
&mut diag,
&cause,
- trait_c_span.map(|span| (span, "type in trait".to_owned())),
+ trait_c_span.map(|span| (span, Cow::from("type in trait"))),
Some(infer::ValuePairs::Terms(ExpectedFound {
expected: trait_ty.into(),
found: impl_ty.into(),
@@ -1814,7 +1921,7 @@ fn compare_type_predicate_entailment<'tcx>(
let impl_ty_span = tcx.def_span(impl_ty_def_id);
let normalize_cause = traits::ObligationCause::misc(impl_ty_span, impl_ty_def_id);
let param_env = ty::ParamEnv::new(
- tcx.mk_predicates(&hybrid_preds.predicates),
+ tcx.mk_clauses(&hybrid_preds.predicates),
Reveal::UserFacing,
hir::Constness::NotConst,
);
@@ -1922,7 +2029,8 @@ pub(super) fn check_type_bounds<'tcx>(
let kind = ty::BoundTyKind::Param(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Ty(kind);
bound_vars.push(bound_var);
- tcx.mk_bound(
+ Ty::new_bound(
+ tcx,
ty::INNERMOST,
ty::BoundTy { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
)
@@ -1932,7 +2040,8 @@ pub(super) fn check_type_bounds<'tcx>(
let kind = ty::BoundRegionKind::BrNamed(param.def_id, param.name);
let bound_var = ty::BoundVariableKind::Region(kind);
bound_vars.push(bound_var);
- tcx.mk_re_late_bound(
+ ty::Region::new_late_bound(
+ tcx,
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_usize(bound_vars.len() - 1), kind },
)
@@ -1941,11 +2050,10 @@ pub(super) fn check_type_bounds<'tcx>(
GenericParamDefKind::Const { .. } => {
let bound_var = ty::BoundVariableKind::Const;
bound_vars.push(bound_var);
- tcx.mk_const(
- ty::ConstKind::Bound(
- ty::INNERMOST,
- ty::BoundVar::from_usize(bound_vars.len() - 1),
- ),
+ ty::Const::new_bound(
+ tcx,
+ ty::INNERMOST,
+ ty::BoundVar::from_usize(bound_vars.len() - 1),
tcx.type_of(param.def_id)
.no_bound_vars()
.expect("const parameter types cannot be generic"),
@@ -1989,7 +2097,7 @@ pub(super) fn check_type_bounds<'tcx>(
.to_predicate(tcx),
),
};
- ty::ParamEnv::new(tcx.mk_predicates(&predicates), Reveal::UserFacing, param_env.constness())
+ ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing, param_env.constness())
};
debug!(?normalize_param_env);
@@ -2003,7 +2111,7 @@ pub(super) fn check_type_bounds<'tcx>(
// A synthetic impl Trait for RPITIT desugaring has no HIR, which we currently use to get the
// span for an impl's associated type. Instead, for these, use the def_span for the synthesized
// associated type.
- let impl_ty_span = if tcx.opt_rpitit_info(impl_ty.def_id).is_some() {
+ let impl_ty_span = if impl_ty.opt_rpitit_info.is_some() {
tcx.def_span(impl_ty_def_id)
} else {
match tcx.hir().get_by_def_id(impl_ty_def_id) {
@@ -2015,7 +2123,7 @@ pub(super) fn check_type_bounds<'tcx>(
_ => bug!(),
}
};
- let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id);
+ let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl_ty_def_id)?;
let normalize_cause = ObligationCause::new(
impl_ty_span,
diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs
index e0ba255cc..13d1abe2a 100644
--- a/compiler/rustc_hir_analysis/src/check/dropck.rs
+++ b/compiler/rustc_hir_analysis/src/check/dropck.rs
@@ -128,7 +128,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
// We don't need to normalize this param-env or anything, since we're only
// substituting it with free params, so no additional param-env normalization
// can occur on top of what has been done in the param_env query itself.
- let param_env = ty::EarlyBinder(tcx.param_env(adt_def_id))
+ let param_env = ty::EarlyBinder::bind(tcx.param_env(adt_def_id))
.subst(tcx, adt_to_impl_substs)
.with_constness(tcx.constness(drop_impl_def_id));
@@ -183,7 +183,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
}
RegionResolutionError::SubSupConflict(_, _, _, a, _, b, _) => format!("{b}: {a}"),
RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => {
- format!("{b}: {a}", a = tcx.mk_re_var(a))
+ format!("{b}: {a}", a = ty::Region::new_var(tcx, a))
}
};
guar = Some(
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index e8785235c..1248f991c 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -11,7 +11,7 @@ use hir::def_id::DefId;
use rustc_errors::{struct_span_err, DiagnosticMessage};
use rustc_hir as hir;
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::symbol::{kw, sym, Symbol};
use rustc_target::spec::abi::Abi;
@@ -53,14 +53,14 @@ fn equate_intrinsic_type<'tcx>(
&& gen_count_ok(own_counts.types, n_tps, "type")
&& gen_count_ok(own_counts.consts, 0, "const")
{
- let fty = tcx.mk_fn_ptr(sig);
+ let fty = Ty::new_fn_ptr(tcx, sig);
let it_def_id = it.owner_id.def_id;
let cause = ObligationCause::new(it.span, it_def_id, ObligationCauseCode::IntrinsicType);
require_same_types(
tcx,
&cause,
ty::ParamEnv::empty(), // FIXME: do all intrinsics have an empty param env?
- tcx.mk_fn_ptr(tcx.fn_sig(it.owner_id).subst_identity()),
+ Ty::new_fn_ptr(tcx, tcx.fn_sig(it.owner_id).subst_identity()),
fty,
);
}
@@ -121,10 +121,11 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
if has_safe_attr != is_in_list {
tcx.sess.struct_span_err(
tcx.def_span(intrinsic_id),
- DiagnosticMessage::Str(format!(
- "intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
- tcx.item_name(intrinsic_id)
- ))).emit();
+ DiagnosticMessage::from(format!(
+ "intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `{}`",
+ tcx.item_name(intrinsic_id)
+ )
+ )).emit();
}
is_in_list
@@ -133,7 +134,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
/// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`,
/// and in `library/core/src/intrinsics.rs`.
pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
- let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)));
+ let param = |n| Ty::new_param(tcx, n, Symbol::intern(&format!("P{}", n)));
let intrinsic_id = it.owner_id.to_def_id();
let intrinsic_name = tcx.item_name(intrinsic_id);
let name_str = intrinsic_name.as_str();
@@ -144,16 +145,18 @@ 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 = tcx.mk_re_late_bound(
+ let region = ty::Region::new_late_bound(
+ tcx,
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) },
);
- let env_region = tcx.mk_re_late_bound(
+ let env_region = ty::Region::new_late_bound(
+ tcx,
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv },
);
let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]);
- (tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
+ (Ty::new_ref(tcx, env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
})
};
@@ -165,15 +168,15 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let (n_tps, inputs, output) = match split[1] {
"cxchg" | "cxchgweak" => (
1,
- vec![tcx.mk_mut_ptr(param(0)), param(0), param(0)],
- tcx.mk_tup(&[param(0), tcx.types.bool]),
+ vec![Ty::new_mut_ptr(tcx, param(0)), param(0), param(0)],
+ Ty::new_tup(tcx, &[param(0), tcx.types.bool]),
),
- "load" => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)),
- "store" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
+ "load" => (1, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)),
+ "store" => (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx)),
"xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" | "min" | "umax"
- | "umin" => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], param(0)),
- "fence" | "singlethreadfence" => (0, Vec::new(), tcx.mk_unit()),
+ | "umin" => (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], param(0)),
+ "fence" | "singlethreadfence" => (0, Vec::new(), Ty::new_unit(tcx)),
op => {
tcx.sess.emit_err(UnrecognizedAtomicOperation { span: it.span, op });
return;
@@ -185,19 +188,19 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let (n_tps, inputs, output) = match intrinsic_name {
sym::abort => (0, Vec::new(), tcx.types.never),
sym::unreachable => (0, Vec::new(), tcx.types.never),
- sym::breakpoint => (0, Vec::new(), tcx.mk_unit()),
+ sym::breakpoint => (0, Vec::new(), Ty::new_unit(tcx)),
sym::size_of | sym::pref_align_of | sym::min_align_of | sym::variant_count => {
(1, Vec::new(), tcx.types.usize)
}
sym::size_of_val | sym::min_align_of_val => {
- (1, vec![tcx.mk_imm_ptr(param(0))], tcx.types.usize)
+ (1, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.types.usize)
}
sym::rustc_peek => (1, vec![param(0)], param(0)),
sym::caller_location => (0, vec![], tcx.caller_location_ty()),
sym::assert_inhabited
| sym::assert_zero_valid
- | sym::assert_mem_uninitialized_valid => (1, Vec::new(), tcx.mk_unit()),
- sym::forget => (1, vec![param(0)], tcx.mk_unit()),
+ | sym::assert_mem_uninitialized_valid => (1, Vec::new(), Ty::new_unit(tcx)),
+ sym::forget => (1, vec![param(0)], Ty::new_unit(tcx)),
sym::transmute | sym::transmute_unchecked => (2, vec![param(0)], param(1)),
sym::prefetch_read_data
| sym::prefetch_write_data
@@ -205,75 +208,79 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
| sym::prefetch_write_instruction => (
1,
vec![
- tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
+ Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
tcx.types.i32,
],
- tcx.mk_unit(),
+ Ty::new_unit(tcx),
),
- sym::drop_in_place => (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_unit()),
+ sym::drop_in_place => (1, vec![Ty::new_mut_ptr(tcx, param(0))], Ty::new_unit(tcx)),
sym::needs_drop => (1, Vec::new(), tcx.types.bool),
- sym::type_name => (1, Vec::new(), tcx.mk_static_str()),
- sym::type_id => (1, Vec::new(), tcx.types.u64),
+ sym::type_name => (1, Vec::new(), Ty::new_static_str(tcx)),
+ sym::type_id => (1, Vec::new(), tcx.types.u128),
sym::offset => (2, vec![param(0), param(1)], param(0)),
sym::arith_offset => (
1,
vec![
- tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
+ Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
tcx.types.isize,
],
- tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
+ 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![tcx.mk_ptr(ty::TypeAndMut {
- ty: tcx.mk_adt(
- tcx.adt_def(option_def_id),
- tcx.mk_substs_from_iter([ty::GenericArg::from(p0)].into_iter()),
- ),
- mutbl: hir::Mutability::Not,
- })],
- tcx.mk_ptr(ty::TypeAndMut { ty: p0, mutbl: hir::Mutability::Not }),
+ vec![Ty::new_ptr(
+ tcx,
+ ty::TypeAndMut {
+ ty: Ty::new_adt(
+ tcx,
+ tcx.adt_def(option_def_id),
+ tcx.mk_substs_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![
- tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
+ Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
tcx.types.usize,
],
- tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
+ Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
),
sym::copy | sym::copy_nonoverlapping => (
1,
vec![
- tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
- tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
+ Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
+ Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
tcx.types.usize,
],
- tcx.mk_unit(),
+ Ty::new_unit(tcx),
),
sym::volatile_copy_memory | sym::volatile_copy_nonoverlapping_memory => (
1,
vec![
- tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
- tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
+ Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
+ Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Not }),
tcx.types.usize,
],
- tcx.mk_unit(),
+ Ty::new_unit(tcx),
),
sym::write_bytes | sym::volatile_set_memory => (
1,
vec![
- tcx.mk_ptr(ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
+ Ty::new_ptr(tcx, ty::TypeAndMut { ty: param(0), mutbl: hir::Mutability::Mut }),
tcx.types.u8,
tcx.types.usize,
],
- tcx.mk_unit(),
+ Ty::new_unit(tcx),
),
sym::sqrtf32 => (0, vec![tcx.types.f32], tcx.types.f32),
sym::sqrtf64 => (0, vec![tcx.types.f64], tcx.types.f64),
@@ -321,10 +328,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::roundevenf64 => (0, vec![tcx.types.f64], tcx.types.f64),
sym::volatile_load | sym::unaligned_volatile_load => {
- (1, vec![tcx.mk_imm_ptr(param(0))], param(0))
+ (1, vec![Ty::new_imm_ptr(tcx, param(0))], param(0))
}
sym::volatile_store | sym::unaligned_volatile_store => {
- (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit())
+ (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx))
}
sym::ctpop
@@ -336,28 +343,34 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
| sym::bitreverse => (1, vec![param(0)], param(0)),
sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
- (1, vec![param(0), param(0)], tcx.mk_tup(&[param(0), tcx.types.bool]))
+ (1, vec![param(0), param(0)], Ty::new_tup(tcx, &[param(0), tcx.types.bool]))
}
- sym::ptr_guaranteed_cmp => {
- (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.u8)
- }
+ sym::ptr_guaranteed_cmp => (
+ 1,
+ vec![Ty::new_imm_ptr(tcx, param(0)), Ty::new_imm_ptr(tcx, param(0))],
+ tcx.types.u8,
+ ),
sym::const_allocate => {
- (0, vec![tcx.types.usize, tcx.types.usize], tcx.mk_mut_ptr(tcx.types.u8))
+ (0, vec![tcx.types.usize, tcx.types.usize], Ty::new_mut_ptr(tcx, tcx.types.u8))
}
sym::const_deallocate => (
0,
- vec![tcx.mk_mut_ptr(tcx.types.u8), tcx.types.usize, tcx.types.usize],
- tcx.mk_unit(),
+ vec![Ty::new_mut_ptr(tcx, tcx.types.u8), tcx.types.usize, tcx.types.usize],
+ Ty::new_unit(tcx),
),
- sym::ptr_offset_from => {
- (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.isize)
- }
- sym::ptr_offset_from_unsigned => {
- (1, vec![tcx.mk_imm_ptr(param(0)), tcx.mk_imm_ptr(param(0))], tcx.types.usize)
- }
+ sym::ptr_offset_from => (
+ 1,
+ vec![Ty::new_imm_ptr(tcx, param(0)), Ty::new_imm_ptr(tcx, param(0))],
+ tcx.types.isize,
+ ),
+ sym::ptr_offset_from_unsigned => (
+ 1,
+ vec![Ty::new_imm_ptr(tcx, param(0)), Ty::new_imm_ptr(tcx, param(0))],
+ tcx.types.usize,
+ ),
sym::unchecked_div | sym::unchecked_rem | sym::exact_div => {
(1, vec![param(0), param(0)], param(0))
}
@@ -376,12 +389,14 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
}
sym::float_to_int_unchecked => (2, vec![param(0)], param(1)),
- sym::assume => (0, vec![tcx.types.bool], tcx.mk_unit()),
+ sym::assume => (0, vec![tcx.types.bool], Ty::new_unit(tcx)),
sym::likely => (0, vec![tcx.types.bool], tcx.types.bool),
sym::unlikely => (0, vec![tcx.types.bool], tcx.types.bool),
- sym::read_via_copy => (1, vec![tcx.mk_imm_ptr(param(0))], param(0)),
- sym::write_via_move => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
+ sym::read_via_copy => (1, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)),
+ sym::write_via_move => {
+ (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx))
+ }
sym::discriminant_value => {
let assoc_items = tcx.associated_item_def_ids(
@@ -392,43 +407,47 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
(
1,
- vec![tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0))],
- tcx.mk_projection(discriminant_def_id, tcx.mk_substs(&[param(0).into()])),
+ vec![Ty::new_imm_ref(
+ tcx,
+ ty::Region::new_late_bound(tcx, ty::INNERMOST, br),
+ param(0),
+ )],
+ Ty::new_projection(tcx, discriminant_def_id, tcx.mk_substs(&[param(0).into()])),
)
}
kw::Try => {
- let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8);
+ let mut_u8 = Ty::new_mut_ptr(tcx, tcx.types.u8);
let try_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
[mut_u8],
- tcx.mk_unit(),
+ Ty::new_unit(tcx),
false,
hir::Unsafety::Normal,
Abi::Rust,
));
let catch_fn_ty = ty::Binder::dummy(tcx.mk_fn_sig(
[mut_u8, mut_u8],
- tcx.mk_unit(),
+ Ty::new_unit(tcx),
false,
hir::Unsafety::Normal,
Abi::Rust,
));
(
0,
- vec![tcx.mk_fn_ptr(try_fn_ty), mut_u8, tcx.mk_fn_ptr(catch_fn_ty)],
+ vec![Ty::new_fn_ptr(tcx, try_fn_ty), mut_u8, Ty::new_fn_ptr(tcx, catch_fn_ty)],
tcx.types.i32,
)
}
sym::va_start | sym::va_end => match mk_va_list_ty(hir::Mutability::Mut) {
- Some((va_list_ref_ty, _)) => (0, vec![va_list_ref_ty], tcx.mk_unit()),
+ Some((va_list_ref_ty, _)) => (0, vec![va_list_ref_ty], Ty::new_unit(tcx)),
None => bug!("`va_list` language item needed for C-variadic intrinsics"),
},
sym::va_copy => match mk_va_list_ty(hir::Mutability::Not) {
Some((va_list_ref_ty, va_list_ty)) => {
- let va_list_ptr_ty = tcx.mk_mut_ptr(va_list_ty);
- (0, vec![va_list_ptr_ty, va_list_ref_ty], tcx.mk_unit())
+ let va_list_ptr_ty = Ty::new_mut_ptr(tcx, va_list_ty);
+ (0, vec![va_list_ptr_ty, va_list_ref_ty], Ty::new_unit(tcx))
}
None => bug!("`va_list` language item needed for C-variadic intrinsics"),
},
@@ -438,11 +457,17 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
None => bug!("`va_list` language item needed for C-variadic intrinsics"),
},
- sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
+ sym::nontemporal_store => {
+ (1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], Ty::new_unit(tcx))
+ }
sym::raw_eq => {
let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
- let param_ty = tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0));
+ let param_ty = Ty::new_imm_ref(
+ tcx,
+ ty::Region::new_late_bound(tcx, ty::INNERMOST, br),
+ param(0),
+ );
(1, vec![param_ty; 2], tcx.types.bool)
}
@@ -451,7 +476,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
sym::const_eval_select => (4, vec![param(0), param(1), param(2)], param(3)),
sym::vtable_size | sym::vtable_align => {
- (0, vec![tcx.mk_imm_ptr(tcx.mk_unit())], tcx.types.usize)
+ (0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize)
}
other => {
@@ -470,7 +495,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
let param = |n| {
let name = Symbol::intern(&format!("P{}", n));
- tcx.mk_ty_param(n, name)
+ Ty::new_param(tcx, n, name)
};
let name = it.ident.name;
@@ -512,7 +537,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
sym::simd_fpowi => (1, vec![param(0), tcx.types.i32], param(0)),
sym::simd_fma => (1, vec![param(0), param(0), param(0)], param(0)),
sym::simd_gather => (3, vec![param(0), param(1), param(2)], param(0)),
- sym::simd_scatter => (3, vec![param(0), param(1), param(2)], tcx.mk_unit()),
+ sym::simd_scatter => (3, vec![param(0), param(1), param(2)], Ty::new_unit(tcx)),
sym::simd_insert => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
sym::simd_extract => (2, vec![param(0), tcx.types.u32], param(1)),
sym::simd_cast
@@ -541,7 +566,7 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
name if name.as_str().starts_with("simd_shuffle") => {
match name.as_str()["simd_shuffle".len()..].parse() {
Ok(n) => {
- let params = vec![param(0), param(0), tcx.mk_array(tcx.types.u32, n)];
+ let params = vec![param(0), param(0), Ty::new_array(tcx, tcx.types.u32, n)];
(2, params, param(1))
}
Err(_) => {
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 3971a4c01..ce2da7cb1 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -188,7 +188,7 @@ fn missing_items_err(
full_impl_span: Span,
) {
let missing_items =
- missing_items.iter().filter(|trait_item| tcx.opt_rpitit_info(trait_item.def_id).is_none());
+ missing_items.iter().filter(|trait_item| trait_item.opt_rpitit_info.is_none());
let missing_items_msg = missing_items
.clone()
@@ -296,7 +296,7 @@ fn default_body_is_unstable(
/// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions.
fn bounds_from_generic_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
- predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
+ predicates: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
) -> (String, String) {
let mut types: FxHashMap<Ty<'tcx>, Vec<DefId>> = FxHashMap::default();
let mut projections = vec![];
@@ -304,7 +304,7 @@ fn bounds_from_generic_predicates<'tcx>(
debug!("predicate {:?}", predicate);
let bound_predicate = predicate.kind();
match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => {
+ ty::ClauseKind::Trait(trait_predicate) => {
let entry = types.entry(trait_predicate.self_ty()).or_default();
let def_id = trait_predicate.def_id();
if Some(def_id) != tcx.lang_items().sized_trait() {
@@ -313,7 +313,7 @@ fn bounds_from_generic_predicates<'tcx>(
entry.push(trait_predicate.def_id());
}
}
- ty::PredicateKind::Clause(ty::Clause::Projection(projection_pred)) => {
+ ty::ClauseKind::Projection(projection_pred) => {
projections.push(bound_predicate.rebind(projection_pred));
}
_ => {}
@@ -362,7 +362,7 @@ fn fn_sig_suggestion<'tcx>(
tcx: TyCtxt<'tcx>,
sig: ty::FnSig<'tcx>,
ident: Ident,
- predicates: impl IntoIterator<Item = (ty::Predicate<'tcx>, Span)>,
+ predicates: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
assoc: ty::AssocItem,
) -> String {
let args = sig
@@ -403,7 +403,30 @@ fn fn_sig_suggestion<'tcx>(
.flatten()
.collect::<Vec<String>>()
.join(", ");
- let output = sig.output();
+ let mut output = sig.output();
+
+ let asyncness = if tcx.asyncness(assoc.def_id).is_async() {
+ output = if let ty::Alias(_, alias_ty) = *output.kind() {
+ tcx.explicit_item_bounds(alias_ty.def_id)
+ .subst_iter_copied(tcx, alias_ty.substs)
+ .find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty())
+ .unwrap_or_else(|| {
+ span_bug!(
+ ident.span,
+ "expected async fn to have `impl Future` output, but it returns {output}"
+ )
+ })
+ } else {
+ span_bug!(
+ ident.span,
+ "expected async fn to have `impl Future` output, but it returns {output}"
+ )
+ };
+ "async "
+ } else {
+ ""
+ };
+
let output = if !output.is_unit() { format!(" -> {output}") } else { String::new() };
let unsafety = sig.unsafety.prefix_str();
@@ -414,7 +437,9 @@ fn fn_sig_suggestion<'tcx>(
// lifetimes between the `impl` and the `trait`, but this should be good enough to
// fill in a significant portion of the missing code, and other subsequent
// suggestions can help the user fix the code.
- format!("{unsafety}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}")
+ format!(
+ "{unsafety}{asyncness}fn {ident}{generics}({args}){output}{where_clauses} {{ todo!() }}"
+ )
}
pub fn ty_kind_suggestion(ty: Ty<'_>) -> Option<&'static str> {
@@ -443,19 +468,16 @@ fn suggestion_signature<'tcx>(
);
match assoc.kind {
- ty::AssocKind::Fn => {
- // We skip the binder here because the binder would deanonymize all
- // late-bound regions, and we don't want method signatures to show up
- // `as for<'r> fn(&'r MyType)`. Pretty-printing handles late-bound
- // regions just fine, showing `fn(&MyType)`.
- fn_sig_suggestion(
- tcx,
- tcx.fn_sig(assoc.def_id).subst(tcx, substs).skip_binder(),
- assoc.ident(tcx),
- tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
- assoc,
- )
- }
+ ty::AssocKind::Fn => fn_sig_suggestion(
+ tcx,
+ tcx.liberate_late_bound_regions(
+ assoc.def_id,
+ tcx.fn_sig(assoc.def_id).subst(tcx, substs),
+ ),
+ assoc.ident(tcx),
+ tcx.predicates_of(assoc.def_id).instantiate_own(tcx, substs),
+ assoc,
+ ),
ty::AssocKind::Type => {
let (generics, where_clauses) = bounds_from_generic_predicates(
tcx,
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 6ab5556e9..5bd6fcb96 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -392,7 +392,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
// Manually recurse over closures and inline consts, because they are the only
// case of nested bodies that share the parent environment.
hir::ExprKind::Closure(&hir::Closure { body, .. })
- | hir::ExprKind::ConstBlock(hir::AnonConst { body, .. }) => {
+ | hir::ExprKind::ConstBlock(hir::ConstBlock { body, .. }) => {
let body = visitor.tcx.hir().body(body);
visitor.visit_body(body);
}
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index b403ee96b..d4748b7ef 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -15,7 +15,7 @@ use rustc_middle::mir::ConstraintCategory;
use rustc_middle::query::Providers;
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
- self, AdtKind, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
+ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
TypeVisitable, TypeVisitableExt, TypeVisitor,
};
use rustc_middle::ty::{GenericArgKind, InternalSubsts};
@@ -81,7 +81,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
self.tcx(),
cause,
param_env,
- ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)),
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg))),
));
}
}
@@ -105,7 +105,12 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
}
f(&mut wfcx);
- let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, span, body_def_id);
+ let assumed_wf_types = match wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)
+ {
+ Ok(wf_types) => wf_types,
+ Err(_guar) => return,
+ };
+
let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types);
let errors = wfcx.select_all_or_error();
@@ -217,10 +222,10 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
check_item_fn(tcx, def_id, item.ident, item.span, sig.decl);
}
hir::ItemKind::Static(ty, ..) => {
- check_item_type(tcx, def_id, ty.span, false);
+ check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid);
}
hir::ItemKind::Const(ty, ..) => {
- check_item_type(tcx, def_id, ty.span, false);
+ check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid);
}
hir::ItemKind::Struct(_, ast_generics) => {
check_type_defn(tcx, item, false);
@@ -242,6 +247,12 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) {
}
// `ForeignItem`s are handled separately.
hir::ItemKind::ForeignMod { .. } => {}
+ hir::ItemKind::TyAlias(hir_ty, ..) => {
+ if tcx.type_of(item.owner_id.def_id).skip_binder().has_opaque_types() {
+ // Bounds are respected for `type X = impl Trait` and `type X = (impl Trait, Y);`
+ check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow);
+ }
+ }
_ => {}
}
}
@@ -258,7 +269,9 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) {
hir::ForeignItemKind::Fn(decl, ..) => {
check_item_fn(tcx, def_id, item.ident, item.span, decl)
}
- hir::ForeignItemKind::Static(ty, ..) => check_item_type(tcx, def_id, ty.span, true),
+ hir::ForeignItemKind::Static(ty, ..) => {
+ check_item_type(tcx, def_id, ty.span, UnsizedHandling::AllowIfForeignTail)
+ }
hir::ForeignItemKind::Type => (),
}
}
@@ -314,7 +327,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
// Gather the bounds with which all other items inside of this trait constrain the GAT.
// This is calculated by taking the intersection of the bounds that each item
// constrains the GAT with individually.
- let mut new_required_bounds: Option<FxHashSet<ty::Predicate<'_>>> = None;
+ let mut new_required_bounds: Option<FxHashSet<ty::Clause<'_>>> = None;
for item in associated_items {
let item_def_id = item.id.owner_id;
// Skip our own GAT, since it does not constrain itself at all.
@@ -411,21 +424,17 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
let mut unsatisfied_bounds: Vec<_> = required_bounds
.into_iter()
.filter(|clause| match clause.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(
- a,
- b,
- ))) => !region_known_to_outlive(
- tcx,
- gat_def_id.def_id,
- param_env,
- &FxIndexSet::default(),
- a,
- b,
- ),
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
- a,
- b,
- ))) => !ty_known_to_outlive(
+ ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(a, b)) => {
+ !region_known_to_outlive(
+ tcx,
+ gat_def_id.def_id,
+ param_env,
+ &FxIndexSet::default(),
+ a,
+ b,
+ )
+ }
+ ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(a, b)) => !ty_known_to_outlive(
tcx,
gat_def_id.def_id,
param_env,
@@ -433,7 +442,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
a,
b,
),
- _ => bug!("Unexpected PredicateKind"),
+ _ => bug!("Unexpected ClauseKind"),
})
.map(|clause| clause.to_string())
.collect();
@@ -481,7 +490,7 @@ fn check_gat_where_clauses(tcx: TyCtxt<'_>, associated_items: &[hir::TraitItemRe
fn augment_param_env<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
- new_predicates: Option<&FxHashSet<ty::Predicate<'tcx>>>,
+ new_predicates: Option<&FxHashSet<ty::Clause<'tcx>>>,
) -> ty::ParamEnv<'tcx> {
let Some(new_predicates) = new_predicates else {
return param_env;
@@ -491,7 +500,7 @@ fn augment_param_env<'tcx>(
return param_env;
}
- let bounds = tcx.mk_predicates_from_iter(
+ let bounds = tcx.mk_clauses_from_iter(
param_env.caller_bounds().iter().chain(new_predicates.iter().cloned()),
);
// FIXME(compiler-errors): Perhaps there is a case where we need to normalize this
@@ -517,7 +526,7 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
wf_tys: &FxIndexSet<Ty<'tcx>>,
gat_def_id: LocalDefId,
gat_generics: &'tcx ty::Generics,
-) -> Option<FxHashSet<ty::Predicate<'tcx>>> {
+) -> Option<FxHashSet<ty::Clause<'tcx>>> {
// The bounds we that we would require from `to_check`
let mut bounds = FxHashSet::default();
@@ -552,22 +561,24 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
// our example, the type was `Self`, which will also be
// `Self` in the GAT.
let ty_param = gat_generics.param_at(*ty_idx, tcx);
- let ty_param = tcx.mk_ty_param(ty_param.index, ty_param.name);
+ let ty_param = Ty::new_param(tcx, ty_param.index, ty_param.name);
// 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 = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
- def_id: region_param.def_id,
- index: region_param.index,
- name: region_param.name,
- });
+ let region_param = ty::Region::new_early_bound(
+ tcx,
+ ty::EarlyBoundRegion {
+ def_id: region_param.def_id,
+ index: region_param.index,
+ name: region_param.name,
+ },
+ );
// The predicate we expect to see. (In our example,
// `Self: 'me`.)
- let clause = ty::PredicateKind::Clause(ty::Clause::TypeOutlives(
- ty::OutlivesPredicate(ty_param, region_param),
- ));
- let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
- bounds.insert(clause);
+ bounds.insert(
+ ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_param, region_param))
+ .to_predicate(tcx),
+ );
}
}
@@ -593,24 +604,32 @@ fn gather_gat_bounds<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
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 = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
- def_id: region_a_param.def_id,
- index: region_a_param.index,
- name: region_a_param.name,
- });
+ let region_a_param = ty::Region::new_early_bound(
+ tcx,
+ ty::EarlyBoundRegion {
+ def_id: region_a_param.def_id,
+ index: region_a_param.index,
+ name: region_a_param.name,
+ },
+ );
// Same for the region.
let region_b_param = gat_generics.param_at(*region_b_idx, tcx);
- let region_b_param = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
- def_id: region_b_param.def_id,
- index: region_b_param.index,
- name: region_b_param.name,
- });
+ let region_b_param = ty::Region::new_early_bound(
+ tcx,
+ ty::EarlyBoundRegion {
+ def_id: region_b_param.def_id,
+ index: region_b_param.index,
+ name: region_b_param.name,
+ },
+ );
// The predicate we expect to see.
- let clause = ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
- ty::OutlivesPredicate(region_a_param, region_b_param),
- ));
- let clause = tcx.mk_predicate(ty::Binder::dummy(clause));
- bounds.insert(clause);
+ bounds.insert(
+ ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
+ region_a_param,
+ region_b_param,
+ ))
+ .to_predicate(tcx),
+ );
}
}
}
@@ -820,83 +839,20 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
let ty = tcx.type_of(param.def_id).subst_identity();
if tcx.features().adt_const_params {
- if let Some(non_structural_match_ty) =
- traits::search_for_adt_const_param_violation(param.span, tcx, ty)
- {
- // We use the same error code in both branches, because this is really the same
- // issue: we just special-case the message for type parameters to make it
- // clearer.
- match non_structural_match_ty.kind() {
- ty::Param(_) => {
- // Const parameters may not have type parameters as their types,
- // because we cannot be sure that the type parameter derives `PartialEq`
- // and `Eq` (just implementing them is not enough for `structural_match`).
- struct_span_err!(
- tcx.sess,
- hir_ty.span,
- E0741,
- "`{ty}` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be \
- used as the type of a const parameter",
- )
- .span_label(
- hir_ty.span,
- format!("`{ty}` may not derive both `PartialEq` and `Eq`"),
- )
- .note(
- "it is not currently possible to use a type parameter as the type of a \
- const parameter",
- )
- .emit();
- }
- ty::Float(_) => {
- struct_span_err!(
- tcx.sess,
- hir_ty.span,
- E0741,
- "`{ty}` is forbidden as the type of a const generic parameter",
- )
- .note("floats do not derive `Eq` or `Ord`, which are required for const parameters")
- .emit();
- }
- ty::FnPtr(_) => {
- struct_span_err!(
- tcx.sess,
- hir_ty.span,
- E0741,
- "using function pointers as const generic parameters is forbidden",
- )
- .emit();
- }
- ty::RawPtr(_) => {
- struct_span_err!(
- tcx.sess,
- hir_ty.span,
- E0741,
- "using raw pointers as const generic parameters is forbidden",
- )
- .emit();
- }
- _ => {
- let mut diag = struct_span_err!(
- tcx.sess,
- hir_ty.span,
- E0741,
- "`{}` must be annotated with `#[derive(PartialEq, Eq)]` to be used as \
- the type of a const parameter",
- non_structural_match_ty,
- );
-
- if ty == non_structural_match_ty {
- diag.span_label(
- hir_ty.span,
- format!("`{ty}` doesn't derive both `PartialEq` and `Eq`"),
- );
- }
-
- diag.emit();
- }
- }
- }
+ enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
+ let trait_def_id =
+ tcx.require_lang_item(LangItem::ConstParamTy, Some(hir_ty.span));
+ wfcx.register_bound(
+ ObligationCause::new(
+ hir_ty.span,
+ param.def_id,
+ ObligationCauseCode::ConstParam(ty),
+ ),
+ wfcx.param_env,
+ ty,
+ trait_def_id,
+ );
+ });
} else {
let err_ty_str;
let mut is_ptr = true;
@@ -1025,7 +981,7 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
// intermediate types must be sized.
let needs_drop_copy = || {
packed && {
- let ty = tcx.type_of(variant.fields.raw.last().unwrap().did).subst_identity();
+ let ty = tcx.type_of(variant.tail().did).subst_identity();
let ty = tcx.erase_regions(ty);
if ty.has_infer() {
tcx.sess
@@ -1078,9 +1034,9 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b
tcx,
cause,
wfcx.param_env,
- ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(
ty::Const::from_anon_const(tcx, discr_def_id.expect_local()),
- )),
+ ))),
));
}
}
@@ -1133,7 +1089,7 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
wfcx.infcx,
wfcx.param_env,
wfcx.body_def_id,
- normalized_bound,
+ normalized_bound.as_predicate(),
bound_span,
)
});
@@ -1154,20 +1110,32 @@ fn check_item_fn(
})
}
-fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_foreign_ty: bool) {
+enum UnsizedHandling {
+ Forbid,
+ Allow,
+ AllowIfForeignTail,
+}
+
+fn check_item_type(
+ tcx: TyCtxt<'_>,
+ item_id: LocalDefId,
+ ty_span: Span,
+ unsized_handling: UnsizedHandling,
+) {
debug!("check_item_type: {:?}", item_id);
enter_wf_checking_ctxt(tcx, ty_span, item_id, |wfcx| {
let ty = tcx.type_of(item_id).subst_identity();
let item_ty = wfcx.normalize(ty_span, Some(WellFormedLoc::Ty(item_id)), ty);
- let mut forbid_unsized = true;
- if allow_foreign_ty {
- let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env);
- if let ty::Foreign(_) = tail.kind() {
- forbid_unsized = false;
+ let forbid_unsized = match unsized_handling {
+ UnsizedHandling::Forbid => true,
+ UnsizedHandling::Allow => false,
+ UnsizedHandling::AllowIfForeignTail => {
+ let tail = tcx.struct_tail_erasing_lifetimes(item_ty, wfcx.param_env);
+ !matches!(tail.kind(), ty::Foreign(_))
}
- }
+ };
wfcx.register_wf_obligation(ty_span, Some(WellFormedLoc::Ty(item_id)), item_ty.into());
if forbid_unsized {
@@ -1398,7 +1366,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
}
let mut param_count = CountParams::default();
let has_region = pred.visit_with(&mut param_count).is_break();
- let substituted_pred = ty::EarlyBinder(pred).subst(tcx, substs);
+ let substituted_pred = ty::EarlyBinder::bind(pred).subst(tcx, substs);
// Don't check non-defaulted params, dependent defaults (including lifetimes)
// or preds with multiple params.
if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region
@@ -1441,7 +1409,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
infcx,
wfcx.param_env.without_const(),
wfcx.body_def_id,
- p,
+ p.as_predicate(),
sp,
)
});
@@ -1503,7 +1471,7 @@ fn check_fn_or_method<'tcx>(
let span = tcx.def_span(def_id);
let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None;
let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 });
- // Check that the argument is a tuple
+ // Check that the argument is a tuple and is sized
if let Some(ty) = inputs.next() {
wfcx.register_bound(
ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),
@@ -1511,6 +1479,12 @@ fn check_fn_or_method<'tcx>(
*ty,
tcx.require_lang_item(hir::LangItem::Tuple, Some(span)),
);
+ wfcx.register_bound(
+ ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall),
+ wfcx.param_env,
+ *ty,
+ tcx.require_lang_item(hir::LangItem::Sized, Some(span)),
+ );
} else {
tcx.sess.span_err(
hir_decl.inputs.last().map_or(span, |input| input.span),
@@ -1572,13 +1546,13 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
if let ty::Alias(ty::Opaque, unshifted_opaque_ty) = *ty.kind()
&& self.seen.insert(unshifted_opaque_ty.def_id)
&& let Some(opaque_def_id) = unshifted_opaque_ty.def_id.as_local()
- && let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
- && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
+ && let origin = tcx.opaque_type_origin(opaque_def_id)
+ && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = origin
&& source == self.fn_def_id
{
let opaque_ty = tcx.fold_regions(unshifted_opaque_ty, |re, _depth| {
match re.kind() {
- ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReError(_) => re,
+ ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReError(_) | ty::ReStatic => re,
r => bug!("unexpected region: {r:?}"),
}
});
@@ -1591,7 +1565,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
self.wfcx.infcx,
self.wfcx.param_env,
self.wfcx.body_def_id,
- bound,
+ bound.as_predicate(),
bound_span,
));
// Set the debruijn index back to innermost here, since we already eagerly
@@ -1799,9 +1773,11 @@ fn check_variances_for_type_defn<'tcx>(
item: &hir::Item<'tcx>,
hir_generics: &hir::Generics<'_>,
) {
- let ty = tcx.type_of(item.owner_id).subst_identity();
- if tcx.has_error_field(ty) {
- return;
+ let identity_substs = ty::InternalSubsts::identity_for_item(tcx, item.owner_id);
+ for field in tcx.adt_def(item.owner_id).all_fields() {
+ if field.ty(tcx, identity_substs).references_error() {
+ return;
+ }
}
let ty_predicates = tcx.predicates_of(item.owner_id);
@@ -1902,7 +1878,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
// We lower empty bounds like `Vec<dyn Copy>:` as
// `WellFormed(Vec<dyn Copy>)`, which will later get checked by
// regular WF checking
- if let ty::PredicateKind::WellFormed(..) = pred.kind().skip_binder() {
+ if let ty::ClauseKind::WellFormed(..) = pred.kind().skip_binder() {
continue;
}
// Match the existing behavior.
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index a98d8e171..79cc43edf 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -336,15 +336,17 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a);
let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
let mt_b = ty::TypeAndMut { ty: ty_b, mutbl: mutbl_b };
- check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty))
+ check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ref(tcx, r_b, ty))
}
(&ty::Ref(_, ty_a, mutbl_a), &ty::RawPtr(mt_b)) => {
let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a };
- check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
+ check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty))
}
- (&ty::RawPtr(mt_a), &ty::RawPtr(mt_b)) => check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty)),
+ (&ty::RawPtr(mt_a), &ty::RawPtr(mt_b)) => {
+ check_mutbl(mt_a, mt_b, &|ty| Ty::new_imm_ptr(tcx, ty))
+ }
(&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b))
if def_a.is_struct() && def_b.is_struct() =>
@@ -571,7 +573,7 @@ fn infringing_fields_error(
.or_default()
.push(error.obligation.cause.span);
}
- if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
+ if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
polarity: ty::ImplPolarity::Positive,
..
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 bd6252344..3bd293126 100644
--- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs
@@ -140,7 +140,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
impl1_def_id: DefId,
impl2_def_id: DefId,
) {
- traits::overlapping_impls(
+ let maybe_overlap = traits::overlapping_impls(
self.tcx,
impl1_def_id,
impl2_def_id,
@@ -148,11 +148,11 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
// inherent impls without warning.
SkipLeakCheck::Yes,
overlap_mode,
- )
- .map_or(true, |overlap| {
+ );
+
+ if let Some(overlap) = maybe_overlap {
self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
- false
- });
+ }
}
fn check_item(&mut self, id: hir::ItemId) {
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index 4524b87a4..5097f4360 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -10,7 +10,6 @@ use rustc_errors::{error_code, struct_span_err};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
-use rustc_span::sym;
use rustc_trait_selection::traits;
mod builtin;
@@ -44,7 +43,7 @@ fn enforce_trait_manually_implementable(
let impl_header_span = tcx.def_span(impl_def_id);
// Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
- if tcx.has_attr(trait_def_id, sym::rustc_deny_explicit_impl) {
+ if tcx.trait_def(trait_def_id).deny_explicit_impl {
let trait_name = tcx.item_name(trait_def_id);
let mut err = struct_span_err!(
tcx.sess,
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index 23beacd2a..025bab140 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -200,35 +200,32 @@ fn do_orphan_check_impl<'tcx>(
NonlocalImpl::DisallowOther,
),
- // trait Id { type This: ?Sized; }
- // impl<T: ?Sized> Id for T {
- // type This = T;
- // }
- // impl<T: ?Sized> AutoTrait for <T as Id>::This {}
- ty::Alias(AliasKind::Projection, _) => (
- LocalImpl::Disallow { problematic_kind: "associated type" },
- NonlocalImpl::DisallowOther,
- ),
-
- // ```
- // struct S<T>(T);
- // impl<T: ?Sized> S<T> {
- // type This = T;
- // }
- // impl<T: ?Sized> AutoTrait for S<T>::This {}
- // ```
- // FIXME(inherent_associated_types): The example code above currently leads to a cycle
- ty::Alias(AliasKind::Inherent, _) => (
- LocalImpl::Disallow { problematic_kind: "associated type" },
- NonlocalImpl::DisallowOther,
- ),
-
- // type Opaque = impl Trait;
- // impl AutoTrait for Opaque {}
- ty::Alias(AliasKind::Opaque, _) => (
- LocalImpl::Disallow { problematic_kind: "opaque type" },
- NonlocalImpl::DisallowOther,
- ),
+ ty::Alias(kind, _) => {
+ let problematic_kind = match kind {
+ // trait Id { type This: ?Sized; }
+ // impl<T: ?Sized> Id for T {
+ // type This = T;
+ // }
+ // impl<T: ?Sized> AutoTrait for <T as Id>::This {}
+ AliasKind::Projection => "associated type",
+ // type Foo = (impl Sized, bool)
+ // impl AutoTrait for Foo {}
+ AliasKind::Weak => "type alias",
+ // type Opaque = impl Trait;
+ // impl AutoTrait for Opaque {}
+ AliasKind::Opaque => "opaque type",
+ // ```
+ // struct S<T>(T);
+ // impl<T: ?Sized> S<T> {
+ // type This = T;
+ // }
+ // impl<T: ?Sized> AutoTrait for S<T>::This {}
+ // ```
+ // FIXME(inherent_associated_types): The example code above currently leads to a cycle
+ AliasKind::Inherent => "associated type",
+ };
+ (LocalImpl::Disallow { problematic_kind }, NonlocalImpl::DisallowOther)
+ }
ty::Bool
| ty::Char
@@ -346,7 +343,7 @@ fn emit_orphan_check_error<'tcx>(
// That way if we had `Vec<MyType>`, we will properly attribute the
// problem to `Vec<T>` and avoid confusing the user if they were to see
// `MyType` in the error.
- ty::Adt(def, _) => tcx.mk_adt(*def, ty::List::empty()),
+ ty::Adt(def, _) => Ty::new_adt(tcx, *def, ty::List::empty()),
_ => ty,
};
let msg = |ty: &str, postfix: &str| {
@@ -608,7 +605,9 @@ fn fast_reject_auto_impl<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId, self_ty:
}
let self_ty_root = match self_ty.kind() {
- ty::Adt(def, _) => tcx.mk_adt(*def, InternalSubsts::identity_for_item(tcx, def.did())),
+ ty::Adt(def, _) => {
+ Ty::new_adt(tcx, *def, InternalSubsts::identity_for_item(tcx, def.did()))
+ }
_ => unimplemented!("unexpected self ty {:?}", self_ty),
};
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index ca0d5509c..f47df4f21 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -380,7 +380,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
}
fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
- self.tcx().ty_error_with_message(span, "bad placeholder type")
+ Ty::new_error_with_message(self.tcx(), span, "bad placeholder type")
}
fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
@@ -390,7 +390,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
// left alone.
r => bug!("unexpected region: {r:?}"),
});
- self.tcx().const_error_with_message(ty, span, "bad placeholder constant")
+ ty::Const::new_error_with_message(self.tcx(), ty, span, "bad placeholder constant")
}
fn projected_ty_from_poly_trait_ref(
@@ -407,7 +407,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
item_segment,
trait_ref.substs,
);
- self.tcx().mk_projection(item_def_id, item_substs)
+ Ty::new_projection(self.tcx(), item_def_id, item_substs)
} else {
// There are no late-bound regions; we can just ignore the binder.
let (mut mpart_sugg, mut inferred_sugg) = (None, None);
@@ -440,7 +440,7 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
self.tcx.replace_late_bound_regions_uncached(
poly_trait_ref,
|_| {
- self.tcx.mk_re_early_bound(ty::EarlyBoundRegion {
+ ty::Region::new_early_bound(self.tcx, ty::EarlyBoundRegion {
def_id: item_def_id,
index: 0,
name: Symbol::intern(&lt_name),
@@ -471,14 +471,15 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
}
_ => {}
}
- self.tcx().ty_error(self.tcx().sess.emit_err(
- errors::AssociatedTypeTraitUninferredGenericParams {
+ Ty::new_error(
+ self.tcx(),
+ self.tcx().sess.emit_err(errors::AssociatedTypeTraitUninferredGenericParams {
span,
inferred_sugg,
bound,
mpart_sugg,
- },
- ))
+ }),
+ )
}
}
@@ -666,17 +667,15 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
tcx.ensure().fn_sig(def_id);
}
- hir::TraitItemKind::Const(.., Some(_)) => {
- tcx.ensure().type_of(def_id);
- }
-
- hir::TraitItemKind::Const(hir_ty, _) => {
+ hir::TraitItemKind::Const(ty, body_id) => {
tcx.ensure().type_of(def_id);
- // Account for `const C: _;`.
- let mut visitor = HirPlaceholderCollector::default();
- visitor.visit_trait_item(trait_item);
- if !tcx.sess.diagnostic().has_stashed_diagnostic(hir_ty.span, StashKey::ItemNoType) {
- placeholder_type_error(tcx, None, visitor.0, false, None, "constant");
+ if !tcx.sess.diagnostic().has_stashed_diagnostic(ty.span, StashKey::ItemNoType)
+ && !(is_suggestable_infer_ty(ty) && body_id.is_some())
+ {
+ // Account for `const C: _;`.
+ let mut visitor = HirPlaceholderCollector::default();
+ visitor.visit_trait_item(trait_item);
+ placeholder_type_error(tcx, None, visitor.0, false, None, "associated constant");
}
}
@@ -721,7 +720,14 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
placeholder_type_error(tcx, None, visitor.0, false, None, "associated type");
}
- hir::ImplItemKind::Const(..) => {}
+ hir::ImplItemKind::Const(ty, _) => {
+ // Account for `const T: _ = ..;`
+ if !is_suggestable_infer_ty(ty) {
+ let mut visitor = HirPlaceholderCollector::default();
+ visitor.visit_impl_item(impl_item);
+ placeholder_type_error(tcx, None, visitor.0, false, None, "associated constant");
+ }
+ }
}
}
@@ -941,7 +947,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
match item {
Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => {
- if !tcx.impl_defaultness(item.id.owner_id).has_value() {
+ if !tcx.defaultness(item.id.owner_id).has_value() {
tcx.sess.emit_err(errors::FunctionNotHaveDefaultImplementation {
span: item.span,
note_span: attr_span,
@@ -986,6 +992,50 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
no_dups.then_some(list)
});
+ let mut deny_explicit_impl = false;
+ let mut implement_via_object = true;
+ if let Some(attr) = tcx.get_attr(def_id, sym::rustc_deny_explicit_impl) {
+ deny_explicit_impl = true;
+ let mut seen_attr = false;
+ for meta in attr.meta_item_list().iter().flatten() {
+ if let Some(meta) = meta.meta_item()
+ && meta.name_or_empty() == sym::implement_via_object
+ && let Some(lit) = meta.name_value_literal()
+ {
+ if seen_attr {
+ tcx.sess.span_err(
+ meta.span,
+ "duplicated `implement_via_object` meta item",
+ );
+ }
+ seen_attr = true;
+
+ match lit.symbol {
+ kw::True => {
+ implement_via_object = true;
+ }
+ kw::False => {
+ implement_via_object = false;
+ }
+ _ => {
+ tcx.sess.span_err(
+ meta.span,
+ format!("unknown literal passed to `implement_via_object` attribute: {}", lit.symbol),
+ );
+ }
+ }
+ } else {
+ tcx.sess.span_err(
+ meta.span(),
+ format!("unknown meta item passed to `rustc_deny_explicit_impl` {:?}", meta),
+ );
+ }
+ }
+ if !seen_attr {
+ tcx.sess.span_err(attr.span, "missing `implement_via_object` meta item");
+ }
+ }
+
ty::TraitDef {
def_id: def_id.to_def_id(),
unsafety,
@@ -996,6 +1046,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
skip_array_during_method_dispatch,
specialization_kind,
must_implement_one_of,
+ implement_via_object,
+ deny_explicit_impl,
}
}
@@ -1124,7 +1176,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<
bug!("unexpected sort of node in fn_sig(): {:?}", x);
}
};
- ty::EarlyBinder(output)
+ ty::EarlyBinder::bind(output)
}
fn infer_return_ty_for_fn_sig<'tcx>(
@@ -1188,7 +1240,7 @@ fn infer_return_ty_for_fn_sig<'tcx>(
} else {
ty::Binder::dummy(tcx.mk_fn_sig(
fn_sig.inputs().iter().copied(),
- tcx.ty_error(guar),
+ Ty::new_error(tcx, guar),
fn_sig.c_variadic,
fn_sig.unsafety,
fn_sig.abi,
@@ -1277,11 +1329,11 @@ fn suggest_impl_trait<'tcx>(
{
continue;
}
- let ocx = ObligationCtxt::new_in_snapshot(&infcx);
+ let ocx = ObligationCtxt::new(&infcx);
let item_ty = ocx.normalize(
&ObligationCause::misc(span, def_id),
param_env,
- tcx.mk_projection(assoc_item_def_id, substs),
+ Ty::new_projection(tcx, assoc_item_def_id, substs),
);
// FIXME(compiler-errors): We may benefit from resolving regions here.
if ocx.select_where_possible().is_empty()
@@ -1312,7 +1364,7 @@ fn impl_trait_ref(
check_impl_constness(tcx, impl_.constness, ast_trait_ref),
)
})
- .map(ty::EarlyBinder)
+ .map(ty::EarlyBinder::bind)
}
fn check_impl_constness(
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index ed60998ec..ccc9f8084 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -9,7 +9,7 @@ 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::Span;
+use rustc_span::{sym, Span};
pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
use rustc_hir::*;
@@ -50,7 +50,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
// We do not allow generic parameters in anon consts if we are inside
// of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
None
- } else if tcx.lazy_normalization() {
+ } else if tcx.features().generic_const_exprs {
let parent_node = tcx.hir().get_parent(hir_id);
if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
&& constant.hir_id == hir_id
@@ -101,6 +101,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
param_def_id_to_index,
has_self: generics.has_self,
has_late_bound_regions: generics.has_late_bound_regions,
+ host_effect_index: None,
};
} else {
// HACK(eddyb) this provides the correct generics when
@@ -123,9 +124,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
{
Some(parent_def_id.to_def_id())
}
- Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) => {
- Some(tcx.typeck_root_def_id(def_id.to_def_id()))
- }
// Exclude `GlobalAsm` here which cannot have generics.
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
if asm.operands.iter().any(|(op, _op_sp)| match op {
@@ -142,11 +140,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
}
}
}
- Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
+ Node::ConstBlock(_)
+ | Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
Some(tcx.typeck_root_def_id(def_id.to_def_id()))
}
Node::Item(item) => match item.kind {
- ItemKind::OpaqueTy(hir::OpaqueTy {
+ ItemKind::OpaqueTy(&hir::OpaqueTy {
origin:
hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
in_trait,
@@ -228,10 +227,12 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
let has_self = opt_self.is_some();
let mut parent_has_self = false;
let mut own_start = has_self as u32;
+ let mut host_effect_index = None;
let parent_count = parent_def_id.map_or(0, |def_id| {
let generics = tcx.generics_of(def_id);
assert!(!has_self);
parent_has_self = generics.has_self;
+ host_effect_index = generics.host_effect_index;
own_start = generics.count() as u32;
generics.parent_count + generics.params.len()
});
@@ -253,11 +254,11 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
// Now create the real type and const parameters.
let type_start = own_start - has_self as u32 + params.len() as u32;
- let mut i = 0;
+ let mut i: u32 = 0;
let mut next_index = || {
let prev = i;
i += 1;
- prev as u32 + type_start
+ prev + type_start
};
const TYPE_DEFAULT_NOT_ALLOWED: &'static str = "defaults for type parameters are only allowed in \
@@ -297,7 +298,13 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
})
}
GenericParamKind::Const { default, .. } => {
- if !matches!(allow_defaults, Defaults::Allowed) && default.is_some() {
+ let is_host_param = tcx.has_attr(param.def_id, sym::rustc_host);
+
+ if !matches!(allow_defaults, Defaults::Allowed)
+ && default.is_some()
+ // `rustc_host` effect params are allowed to have defaults.
+ && !is_host_param
+ {
tcx.sess.span_err(
param.span,
"defaults for const parameters are only allowed in \
@@ -305,8 +312,18 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
);
}
+ let index = next_index();
+
+ if is_host_param {
+ if let Some(idx) = host_effect_index {
+ bug!("parent also has host effect param? index: {idx}, def: {def_id:?}");
+ }
+
+ host_effect_index = Some(parent_count + index as usize);
+ }
+
Some(ty::GenericParamDef {
- index: next_index(),
+ index,
name: param.name.ident().name,
def_id: param.def_id.to_def_id(),
pure_wrt_drop: param.pure_wrt_drop,
@@ -339,17 +356,14 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
}
// provide junk type parameter defs for const blocks.
- if let Node::AnonConst(_) = node {
- let parent_node = tcx.hir().get_parent(hir_id);
- if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node {
- params.push(ty::GenericParamDef {
- index: next_index(),
- name: Symbol::intern("<const_ty>"),
- def_id: def_id.to_def_id(),
- pure_wrt_drop: false,
- kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
- });
- }
+ if let Node::ConstBlock(_) = node {
+ params.push(ty::GenericParamDef {
+ index: next_index(),
+ name: Symbol::intern("<const_ty>"),
+ def_id: def_id.to_def_id(),
+ pure_wrt_drop: false,
+ kind: ty::GenericParamDefKind::Type { has_default: false, synthetic: false },
+ });
}
let param_def_id_to_index = params.iter().map(|param| (param.def_id, param.index)).collect();
@@ -361,6 +375,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
param_def_id_to_index,
has_self: has_self || parent_has_self,
has_late_bound_regions: has_late_bound_regions(tcx, node),
+ host_effect_index,
}
}
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 948b903e5..57f74172e 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -1,5 +1,5 @@
use super::ItemCtxt;
-use crate::astconv::{AstConv, OnlySelfBounds};
+use crate::astconv::{AstConv, PredicateFilter};
use rustc_hir as hir;
use rustc_infer::traits::util;
use rustc_middle::ty::subst::InternalSubsts;
@@ -19,32 +19,34 @@ fn associated_type_bounds<'tcx>(
assoc_item_def_id: LocalDefId,
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
span: Span,
-) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
- let item_ty = tcx.mk_projection(
+) -> &'tcx [(ty::Clause<'tcx>, Span)] {
+ let item_ty = Ty::new_projection(
+ tcx,
assoc_item_def_id.to_def_id(),
InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
);
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
- let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
+ let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
// Associated types are implicitly sized unless a `?Sized` bound is found
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
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() {
- ty::PredicateKind::Clause(ty::Clause::Trait(tr)) => tr.self_ty() == item_ty,
- ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => {
- proj.projection_ty.self_ty() == item_ty
- }
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => outlives.0 == item_ty,
+ 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.predicates().chain(bounds_from_parent));
+ let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent));
debug!(
"associated_type_bounds({}) = {:?}",
tcx.def_path_str(assoc_item_def_id.to_def_id()),
@@ -64,33 +66,34 @@ fn opaque_type_bounds<'tcx>(
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
item_ty: Ty<'tcx>,
span: Span,
-) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
+) -> &'tcx [(ty::Clause<'tcx>, Span)] {
ty::print::with_no_queries!({
let icx = ItemCtxt::new(tcx, opaque_def_id);
- let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false));
+ let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All);
// Opaque types are implicitly sized unless a `?Sized` bound is found
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
debug!(?bounds);
- tcx.arena.alloc_from_iter(bounds.predicates())
+ tcx.arena.alloc_from_iter(bounds.clauses())
})
}
pub(super) fn explicit_item_bounds(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
-) -> ty::EarlyBinder<&'_ [(ty::Predicate<'_>, Span)]> {
+) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> {
match tcx.opt_rpitit_info(def_id.to_def_id()) {
// 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 opaque_ty = item.expect_opaque_ty();
- return ty::EarlyBinder(opaque_type_bounds(
+ return ty::EarlyBinder::bind(opaque_type_bounds(
tcx,
opaque_def_id.expect_local(),
opaque_ty.bounds,
- tcx.mk_projection(
+ Ty::new_projection(
+ tcx,
def_id.to_def_id(),
ty::InternalSubsts::identity_for_item(tcx, def_id),
),
@@ -116,25 +119,23 @@ pub(super) fn explicit_item_bounds(
}) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
- tcx.mk_projection(def_id.to_def_id(), substs)
+ Ty::new_projection(tcx, def_id.to_def_id(), substs)
} else {
- tcx.mk_opaque(def_id.to_def_id(), substs)
+ Ty::new_opaque(tcx, def_id.to_def_id(), substs)
};
opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
}
+ hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
_ => bug!("item_bounds called on {:?}", def_id),
};
- ty::EarlyBinder(bounds)
+ ty::EarlyBinder::bind(bounds)
}
pub(super) fn item_bounds(
tcx: TyCtxt<'_>,
def_id: DefId,
-) -> ty::EarlyBinder<&'_ ty::List<ty::Predicate<'_>>> {
+) -> ty::EarlyBinder<&'_ ty::List<ty::Clause<'_>>> {
tcx.explicit_item_bounds(def_id).map_bound(|bounds| {
- tcx.mk_predicates_from_iter(util::elaborate(
- tcx,
- bounds.iter().map(|&(bound, _span)| bound),
- ))
+ tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound)))
})
}
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index e5b5dae55..129366641 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -1,8 +1,8 @@
-use crate::astconv::{AstConv, OnlySelfBounds};
+use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
use crate::bounds::Bounds;
use crate::collect::ItemCtxt;
use crate::constrained_generic_params as cgp;
-use hir::{HirId, Node};
+use hir::{HirId, Lifetime, Node};
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
@@ -10,9 +10,9 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{GenericPredicates, ToPredicate};
+use rustc_middle::ty::{GenericPredicates, Generics, ImplTraitInTraitData, ToPredicate};
use rustc_span::symbol::{sym, Ident};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::{Span, Symbol, DUMMY_SP};
/// Returns a list of all type predicates (explicit and implicit) for the definition with
/// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
@@ -62,6 +62,67 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
use rustc_hir::*;
+ match tcx.opt_rpitit_info(def_id.to_def_id()) {
+ Some(ImplTraitInTraitData::Trait { opaque_def_id, fn_def_id }) => {
+ let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local());
+ let opaque_ty_node = tcx.hir().get(opaque_ty_id);
+ let Node::Item(&Item { kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }), .. }) = opaque_ty_node else {
+ bug!("unexpected {opaque_ty_node:?}")
+ };
+
+ let mut predicates = Vec::new();
+
+ // RPITITs should inherit the predicates of their parent. This is
+ // both to ensure that the RPITITs are only instantiated when the
+ // parent predicates would hold, and also so that the param-env
+ // inherits these predicates as assumptions.
+ let identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+ predicates.extend(
+ tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_substs),
+ );
+
+ // We also install bidirectional outlives predicates for the RPITIT
+ // to keep the duplicates lifetimes from opaque lowering in sync.
+ compute_bidirectional_outlives_predicates(
+ tcx,
+ def_id,
+ lifetime_mapping.iter().map(|(lifetime, def_id)| {
+ (*lifetime, (*def_id, lifetime.ident.name, lifetime.ident.span))
+ }),
+ tcx.generics_of(def_id.to_def_id()),
+ &mut predicates,
+ );
+
+ return ty::GenericPredicates {
+ parent: Some(tcx.parent(def_id.to_def_id())),
+ predicates: tcx.arena.alloc_from_iter(predicates),
+ };
+ }
+
+ Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
+ let assoc_item = tcx.associated_item(def_id);
+ let trait_assoc_predicates =
+ tcx.explicit_predicates_of(assoc_item.trait_item_def_id.unwrap());
+
+ let impl_assoc_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+ let impl_def_id = tcx.parent(fn_def_id);
+ let impl_trait_ref_substs =
+ tcx.impl_trait_ref(impl_def_id).unwrap().subst_identity().substs;
+
+ let impl_assoc_substs =
+ impl_assoc_identity_substs.rebase_onto(tcx, impl_def_id, impl_trait_ref_substs);
+
+ let impl_predicates = trait_assoc_predicates.instantiate_own(tcx, impl_assoc_substs);
+
+ return ty::GenericPredicates {
+ parent: Some(impl_def_id),
+ predicates: tcx.arena.alloc_from_iter(impl_predicates),
+ };
+ }
+
+ None => {}
+ }
+
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let node = tcx.hir().get(hir_id);
@@ -75,7 +136,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
// We use an `IndexSet` to preserve order of insertion.
// Preserving the order of insertion is important here so as not to break UI tests.
- let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default();
+ let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
let ast_generics = match node {
Node::TraitItem(item) => item.generics,
@@ -125,8 +186,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
if let Some(self_bounds) = is_trait {
predicates.extend(
icx.astconv()
- .compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false))
- .predicates(),
+ .compute_bounds(tcx.types.self_param, self_bounds, PredicateFilter::All)
+ .clauses(),
);
}
@@ -175,22 +236,24 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
param.span,
);
trace!(?bounds);
- predicates.extend(bounds.predicates());
+ predicates.extend(bounds.clauses());
trace!(?predicates);
}
GenericParamKind::Const { .. } => {
let name = param.name.ident().name;
let param_const = ty::ParamConst::new(index, name);
- let ct_ty = tcx.type_of(param.def_id.to_def_id()).subst_identity();
+ let ct_ty = tcx
+ .type_of(param.def_id.to_def_id())
+ .no_bound_vars()
+ .expect("const parameters cannot be generic");
- let ct = tcx.mk_const(param_const, ct_ty);
+ let ct = ty::Const::new_param(tcx, param_const, ct_ty);
- let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
- ty::Clause::ConstArgHasType(ct, ct_ty),
- ))
- .to_predicate(tcx);
- predicates.insert((predicate, param.span));
+ predicates.insert((
+ ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx),
+ param.span,
+ ));
index += 1;
}
@@ -219,7 +282,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
} else {
let span = bound_pred.bounded_ty.span;
let predicate = ty::Binder::bind_with_vars(
- ty::PredicateKind::WellFormed(ty.into()),
+ ty::ClauseKind::WellFormed(ty.into()),
bound_vars,
);
predicates.insert((predicate.to_predicate(tcx), span));
@@ -234,7 +297,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
bound_vars,
OnlySelfBounds(false),
);
- predicates.extend(bounds.predicates());
+ predicates.extend(bounds.clauses());
}
hir::WherePredicate::RegionPredicate(region_pred) => {
@@ -246,11 +309,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}
_ => bug!(),
};
- let pred = ty::Binder::dummy(ty::PredicateKind::Clause(
- ty::Clause::RegionOutlives(ty::OutlivesPredicate(r1, r2)),
- ))
- .to_predicate(icx.tcx);
-
+ let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2))
+ .to_predicate(icx.tcx);
(pred, span)
}))
}
@@ -293,39 +353,22 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
bug!("unexpected {opaque_ty_node:?}")
};
debug!(?lifetimes);
- for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) {
- let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
- let orig_region = icx.astconv().ast_region_to_region(&arg, None);
- if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
- // Only early-bound regions can point to the original generic parameter.
- continue;
- }
- let hir::GenericParamKind::Lifetime { .. } = duplicate.kind else { continue };
- let dup_def = duplicate.def_id.to_def_id();
-
- let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() };
-
- let dup_region = tcx.mk_re_early_bound(ty::EarlyBoundRegion {
- def_id: dup_def,
- index: dup_index,
- name: duplicate.name.ident().name,
- });
- predicates.push((
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
- ty::OutlivesPredicate(orig_region, dup_region),
- )))
- .to_predicate(icx.tcx),
- duplicate.span,
- ));
- predicates.push((
- ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
- ty::OutlivesPredicate(dup_region, orig_region),
- )))
- .to_predicate(icx.tcx),
- duplicate.span,
- ));
- }
+ let lifetime_mapping = std::iter::zip(lifetimes, ast_generics.params)
+ .map(|(arg, dup)| {
+ let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
+ (**arg, dup)
+ })
+ .filter(|(_, dup)| matches!(dup.kind, hir::GenericParamKind::Lifetime { .. }))
+ .map(|(lifetime, dup)| (lifetime, (dup.def_id, dup.name.ident().name, dup.span)));
+
+ compute_bidirectional_outlives_predicates(
+ tcx,
+ def_id,
+ lifetime_mapping,
+ generics,
+ &mut predicates,
+ );
debug!(?predicates);
}
@@ -335,13 +378,53 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}
}
+/// Opaques have duplicated lifetimes and we need to compute bidirectional outlives predicates to
+/// enforce that these lifetimes stay in sync.
+fn compute_bidirectional_outlives_predicates<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ item_def_id: LocalDefId,
+ lifetime_mapping: impl Iterator<Item = (Lifetime, (LocalDefId, Symbol, Span))>,
+ generics: &Generics,
+ predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
+) {
+ let icx = ItemCtxt::new(tcx, item_def_id);
+
+ for (arg, (dup_def, name, span)) in lifetime_mapping {
+ let orig_region = icx.astconv().ast_region_to_region(&arg, None);
+ if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
+ // There is no late-bound lifetime to actually match up here, since the lifetime doesn't
+ // show up in the opaque's parent's substs.
+ continue;
+ }
+
+ let Some(dup_index) = generics.param_def_id_to_index(icx.tcx, dup_def.to_def_id()) else { bug!() };
+
+ let dup_region = ty::Region::new_early_bound(
+ tcx,
+ ty::EarlyBoundRegion { def_id: dup_def.to_def_id(), index: dup_index, name },
+ );
+
+ predicates.push((
+ ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region))
+ .to_predicate(tcx),
+ span,
+ ));
+
+ predicates.push((
+ ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region))
+ .to_predicate(tcx),
+ span,
+ ));
+ }
+}
+
fn const_evaluatable_predicates_of(
tcx: TyCtxt<'_>,
def_id: LocalDefId,
-) -> FxIndexSet<(ty::Predicate<'_>, Span)> {
+) -> FxIndexSet<(ty::Clause<'_>, Span)> {
struct ConstCollector<'tcx> {
tcx: TyCtxt<'tcx>,
- preds: FxIndexSet<(ty::Predicate<'tcx>, Span)>,
+ preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
}
impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> {
@@ -349,11 +432,8 @@ fn const_evaluatable_predicates_of(
let ct = ty::Const::from_anon_const(self.tcx, c.def_id);
if let ty::ConstKind::Unevaluated(_) = ct.kind() {
let span = self.tcx.def_span(c.def_id);
- self.preds.insert((
- ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct))
- .to_predicate(self.tcx),
- span,
- ));
+ self.preds
+ .insert((ty::ClauseKind::ConstEvaluatable(ct).to_predicate(self.tcx), span));
}
}
@@ -441,13 +521,9 @@ pub(super) fn explicit_predicates_of<'tcx>(
.iter()
.copied()
.filter(|(pred, _)| match pred.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(tr)) => !is_assoc_item_ty(tr.self_ty()),
- ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => {
- !is_assoc_item_ty(proj.projection_ty.self_ty())
- }
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => {
- !is_assoc_item_ty(outlives.0)
- }
+ ty::ClauseKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()),
+ ty::ClauseKind::Projection(proj) => !is_assoc_item_ty(proj.projection_ty.self_ty()),
+ ty::ClauseKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
_ => true,
})
.collect();
@@ -460,7 +536,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
}
}
} else {
- if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() {
+ 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 parent_def_id = tcx.hir().get_parent_item(hir_id);
@@ -488,9 +564,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
.predicates
.into_iter()
.filter(|(pred, _)| {
- if let ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, _)) =
- pred.kind().skip_binder()
- {
+ if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() {
match ct.kind() {
ty::ConstKind::Param(param_const) => {
let defaulted_param_idx = tcx
@@ -544,19 +618,6 @@ pub(super) fn explicit_predicates_of<'tcx>(
}
}
-#[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),
-}
-
/// Ensures that the super-predicates of the trait with a `DefId`
/// of `trait_def_id` are converted and stored. This also ensures that
/// the transitive super-predicates are converted.
@@ -578,11 +639,15 @@ pub(super) fn implied_predicates_of(
tcx: TyCtxt<'_>,
trait_def_id: LocalDefId,
) -> ty::GenericPredicates<'_> {
- if tcx.is_trait_alias(trait_def_id.to_def_id()) {
- implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::All)
- } else {
- tcx.super_predicates_of(trait_def_id)
- }
+ implied_predicates_with_filter(
+ tcx,
+ trait_def_id.to_def_id(),
+ if tcx.is_trait_alias(trait_def_id.to_def_id()) {
+ PredicateFilter::All
+ } else {
+ PredicateFilter::SelfAndAssociatedTypeBounds
+ },
+ )
}
/// Ensures that the super-predicates of the trait with a `DefId`
@@ -615,48 +680,18 @@ pub(super) fn implied_predicates_with_filter(
let icx = ItemCtxt::new(tcx, trait_def_id);
let self_param_ty = tcx.types.self_param;
- let (superbounds, where_bounds_that_match) = match filter {
- PredicateFilter::All => (
- // Convert the bounds that follow the colon (or equal in trait aliases)
- icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(false)),
- // Also include all where clause bounds
- icx.type_parameter_bounds_in_generics(
- generics,
- item.owner_id.def_id,
- self_param_ty,
- OnlySelfBounds(false),
- None,
- ),
- ),
- PredicateFilter::SelfOnly => (
- // Convert the bounds that follow the colon (or equal in trait aliases)
- icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(true)),
- // Include where clause bounds for `Self`
- icx.type_parameter_bounds_in_generics(
- generics,
- item.owner_id.def_id,
- self_param_ty,
- OnlySelfBounds(true),
- None,
- ),
- ),
- PredicateFilter::SelfThatDefines(assoc_name) => (
- // Convert the bounds that follow the colon (or equal) that reference the associated name
- icx.astconv().compute_bounds_that_match_assoc_item(self_param_ty, bounds, assoc_name),
- // Include where clause bounds for `Self` that reference the associated name
- icx.type_parameter_bounds_in_generics(
- generics,
- item.owner_id.def_id,
- self_param_ty,
- OnlySelfBounds(true),
- Some(assoc_name),
- ),
- ),
- };
+ let superbounds = icx.astconv().compute_bounds(self_param_ty, bounds, filter);
+
+ let where_bounds_that_match = icx.type_parameter_bounds_in_generics(
+ generics,
+ item.owner_id.def_id,
+ self_param_ty,
+ filter,
+ );
// Combine the two lists to form the complete set of superbounds:
let implied_bounds =
- &*tcx.arena.alloc_from_iter(superbounds.predicates().chain(where_bounds_that_match));
+ &*tcx.arena.alloc_from_iter(superbounds.clauses().chain(where_bounds_that_match));
debug!(?implied_bounds);
// Now require that immediate supertraits are converted, which will, in
@@ -665,7 +700,7 @@ pub(super) fn implied_predicates_with_filter(
if matches!(filter, PredicateFilter::SelfOnly) {
for &(pred, span) in implied_bounds {
debug!("superbound: {:?}", pred);
- if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder()
+ if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
&& bound.polarity == ty::ImplPolarity::Positive
{
tcx.at(span).super_predicates_of(bound.def_id());
@@ -684,6 +719,7 @@ pub(super) fn type_param_predicates(
(item_def_id, def_id, assoc_name): (LocalDefId, LocalDefId, Ident),
) -> ty::GenericPredicates<'_> {
use rustc_hir::*;
+ use rustc_middle::ty::Ty;
// In the AST, bounds can derive from two places. Either
// written inline like `<T: Foo>` or in a where-clause like
@@ -693,7 +729,7 @@ pub(super) fn type_param_predicates(
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()];
- let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id));
+ let ty = Ty::new_param(tcx, index, tcx.hir().ty_param_name(def_id));
// Don't look for bounds where the type parameter isn't in scope.
let parent = if item_def_id == param_owner {
@@ -721,7 +757,7 @@ pub(super) fn type_param_predicates(
ItemKind::Fn(.., generics, _)
| ItemKind::Impl(&hir::Impl { generics, .. })
| ItemKind::TyAlias(_, generics)
- | ItemKind::OpaqueTy(OpaqueTy {
+ | ItemKind::OpaqueTy(&OpaqueTy {
generics,
origin: hir::OpaqueTyOrigin::TyAlias { .. },
..
@@ -757,12 +793,11 @@ pub(super) fn type_param_predicates(
ast_generics,
def_id,
ty,
- OnlySelfBounds(true),
- Some(assoc_name),
+ PredicateFilter::SelfThatDefines(assoc_name),
)
.into_iter()
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(data)) => data.self_ty().is_param(index),
+ ty::ClauseKind::Trait(data) => data.self_ty().is_param(index),
_ => false,
}),
);
@@ -782,9 +817,8 @@ impl<'tcx> ItemCtxt<'tcx> {
ast_generics: &'tcx hir::Generics<'tcx>,
param_def_id: LocalDefId,
ty: Ty<'tcx>,
- only_self_bounds: OnlySelfBounds,
- assoc_name: Option<Ident>,
- ) -> Vec<(ty::Predicate<'tcx>, Span)> {
+ filter: PredicateFilter,
+ ) -> Vec<(ty::Clause<'tcx>, Span)> {
let mut bounds = Bounds::default();
for predicate in ast_generics.predicates {
@@ -792,9 +826,23 @@ impl<'tcx> ItemCtxt<'tcx> {
continue;
};
+ let (only_self_bounds, assoc_name) = match filter {
+ PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
+ (OnlySelfBounds(false), None)
+ }
+ PredicateFilter::SelfOnly => (OnlySelfBounds(true), None),
+ PredicateFilter::SelfThatDefines(assoc_name) => {
+ (OnlySelfBounds(true), Some(assoc_name))
+ }
+ };
+
+ // Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
+ // want to only consider predicates with `Self: ...`, but we don't want
+ // `OnlySelfBounds(true)` since we want to collect the nested associated
+ // type bound as well.
let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
ty
- } else if !only_self_bounds.0 {
+ } else if matches!(filter, PredicateFilter::All) {
self.to_ty(predicate.bounded_ty)
} else {
continue;
@@ -813,7 +861,7 @@ impl<'tcx> ItemCtxt<'tcx> {
);
}
- bounds.predicates().collect()
+ bounds.clauses().collect()
}
#[instrument(level = "trace", skip(self))]
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 794812a5c..acd0bcd8e 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -22,7 +22,7 @@ use rustc_middle::ty::{self, TyCtxt, TypeSuperVisitable, TypeVisitor};
use rustc_session::lint;
use rustc_span::def_id::DefId;
use rustc_span::symbol::{sym, Ident};
-use rustc_span::Span;
+use rustc_span::{Span, DUMMY_SP};
use std::fmt;
use crate::errors;
@@ -338,7 +338,17 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::TraitRefBoundary { .. } => {
// We should only see super trait lifetimes if there is a `Binder` above
- assert!(supertrait_bound_vars.is_empty());
+ // 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(
+ DUMMY_SP,
+ format!(
+ "found supertrait lifetimes without a binder to append \
+ them to: {supertrait_bound_vars:?}"
+ ),
+ );
+ }
break (vec![], BinderScopeType::Normal);
}
@@ -556,7 +566,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
});
}
}
- hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+ hir::ItemKind::OpaqueTy(&hir::OpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
generics,
..
@@ -1344,12 +1354,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
Scope::Binder {
where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
} => {
- let mut err = self.tcx.sess.struct_span_err(
- lifetime_ref.ident.span,
- "`impl Trait` can only mention lifetimes bound at the fn or impl level",
- );
- err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
- err.emit();
+ self.tcx.sess.emit_err(errors::LateBoundInApit::Lifetime {
+ span: lifetime_ref.ident.span,
+ param_span: self.tcx.def_span(region_def_id),
+ });
return;
}
Scope::Root { .. } => break,
@@ -1379,6 +1387,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
let mut late_depth = 0;
let mut scope = self.scope;
let mut crossed_anon_const = false;
+
let result = loop {
match *scope {
Scope::Body { s, .. } => {
@@ -1446,6 +1455,50 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
return;
}
+ // We may fail to resolve higher-ranked ty/const vars that are mentioned by APIT.
+ // AST-based resolution does not care for impl-trait desugaring, which are the
+ // responsibility of lowering. This may create a mismatch between the resolution
+ // AST found (`param_def_id`) which points to HRTB, and what HIR allows.
+ // ```
+ // fn foo(x: impl for<T> Trait<Assoc = impl Trait2<T>>) {}
+ // ```
+ //
+ // In such case, walk back the binders to diagnose it properly.
+ let mut scope = self.scope;
+ loop {
+ match *scope {
+ Scope::Binder {
+ where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
+ } => {
+ let guar = self.tcx.sess.emit_err(match self.tcx.def_kind(param_def_id) {
+ DefKind::TyParam => errors::LateBoundInApit::Type {
+ span: self.tcx.hir().span(hir_id),
+ param_span: self.tcx.def_span(param_def_id),
+ },
+ DefKind::ConstParam => errors::LateBoundInApit::Const {
+ span: self.tcx.hir().span(hir_id),
+ param_span: self.tcx.def_span(param_def_id),
+ },
+ kind => {
+ bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
+ }
+ });
+ self.map.defs.insert(hir_id, ResolvedArg::Error(guar));
+ return;
+ }
+ Scope::Root { .. } => break,
+ Scope::Binder { s, .. }
+ | Scope::Body { s, .. }
+ | Scope::Elision { s, .. }
+ | Scope::ObjectLifetimeDefault { s, .. }
+ | Scope::Supertrait { s, .. }
+ | Scope::TraitRefBoundary { s, .. }
+ | Scope::AnonConstBoundary { s } => {
+ scope = s;
+ }
+ }
+ }
+
self.tcx.sess.delay_span_bug(
self.tcx.hir().span(hir_id),
format!("could not resolve {param_def_id:?}"),
@@ -1761,7 +1814,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
let bound_predicate = pred.kind();
match bound_predicate.skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(data)) => {
+ ty::ClauseKind::Trait(data) => {
// The order here needs to match what we would get from `subst_supertrait`
let pred_bound_vars = bound_predicate.bound_vars();
let mut all_bound_vars = bound_vars.clone();
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 8e082d3c5..3755342ae 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -16,6 +16,7 @@ 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 Node::AnonConst(_) = tcx.hir().get(hir_id) else { panic!() };
@@ -25,21 +26,15 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
let (generics, arg_idx) = match parent_node {
// Easy case: arrays repeat expressions.
- Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. })
+ Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
if constant.hir_id() == hir_id =>
{
return tcx.types.usize
}
- Node::Ty(&Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => {
+ Node::Ty(&hir::Ty { kind: TyKind::Typeof(ref e), .. }) if e.hir_id == hir_id => {
return tcx.typeck(def_id).node_type(e.hir_id)
}
- Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. })
- if anon_const.hir_id == hir_id =>
- {
- let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
- return substs.as_inline_const().ty()
- }
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
if asm.operands.iter().any(|(op, _op_sp)| match op {
@@ -73,7 +68,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
) =>
{
let Some(trait_def_id) = trait_ref.trait_def_id() else {
- return tcx.ty_error_with_message(tcx.def_span(def_id), "Could not find trait");
+ return Ty::new_error_with_message(tcx,tcx.def_span(def_id), "Could not find trait");
};
let assoc_items = tcx.associated_items(trait_def_id);
let assoc_item = assoc_items.find_by_name_and_kind(
@@ -85,7 +80,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
.expect("const parameter types cannot be generic")
} else {
// FIXME(associated_const_equality): add a useful error message here.
- tcx.ty_error_with_message(tcx.def_span(def_id), "Could not find associated const on trait")
+ Ty::new_error_with_message(tcx,tcx.def_span(def_id), "Could not find associated const on trait")
}
}
@@ -105,7 +100,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
// arm would handle this.
//
// I believe this match arm is only needed for GAT but I am not 100% sure - BoxyUwU
- Node::Ty(hir_ty @ Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
+ Node::Ty(hir_ty @ hir::Ty { kind: TyKind::Path(QPath::TypeRelative(_, segment)), .. }) => {
// Find the Item containing the associated type so we can create an ItemCtxt.
// Using the ItemCtxt convert the HIR for the unresolved assoc type into a
// ty which is a fully resolved projection.
@@ -143,7 +138,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
(generics, arg_index)
} else {
// I dont think it's possible to reach this but I'm not 100% sure - BoxyUwU
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
"unexpected non-GAT usage of an anon const",
);
@@ -160,7 +155,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
// As there is no relevant param for `def_id`, we simply return
// `None` here.
let Some(type_dependent_def) = tables.type_dependent_def_id(parent_node_id) else {
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
format!("unable to find type-dependent def for {:?}", parent_node_id),
);
@@ -180,12 +175,12 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
(tcx.generics_of(type_dependent_def), idx)
}
- Node::Ty(&Ty { kind: TyKind::Path(_), .. })
+ Node::Ty(&hir::Ty { kind: TyKind::Path(_), .. })
| Node::Expr(&Expr { kind: ExprKind::Path(_) | ExprKind::Struct(..), .. })
| Node::TraitRef(..)
| Node::Pat(_) => {
let path = match parent_node {
- Node::Ty(&Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
+ Node::Ty(&hir::Ty { kind: TyKind::Path(QPath::Resolved(_, path)), .. })
| Node::TraitRef(&TraitRef { path, .. }) => &*path,
Node::Expr(&Expr {
kind:
@@ -201,14 +196,14 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
if let Some(path) = get_path_containing_arg_in_pat(pat, hir_id) {
path
} else {
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
format!("unable to find const parent for {} in pat {:?}", hir_id, pat),
);
}
}
_ => {
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
format!("unexpected const parent path {:?}", parent_node),
);
@@ -230,7 +225,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
.position(|ct| ct.hir_id == hir_id)
.map(|idx| (idx, seg)))
}) else {
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
"no arg matching AnonConst in path",
);
@@ -239,7 +234,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
let generics = match tcx.res_generics_def_id(segment.res) {
Some(def_id) => tcx.generics_of(def_id),
None => {
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
format!("unexpected anon const res {:?} in path: {:?}", segment.res, path),
);
@@ -249,7 +244,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
(generics, arg_index)
}
- _ => return tcx.ty_error_with_message(
+ _ => return Ty::new_error_with_message(tcx,
tcx.def_span(def_id),
format!("unexpected const parent in type_of(): {parent_node:?}"),
),
@@ -275,7 +270,8 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
{
tcx.type_of(param_def_id).no_bound_vars().expect("const parameter types cannot be generic")
} else {
- return tcx.ty_error_with_message(
+ return Ty::new_error_with_message(
+ tcx,
tcx.def_span(def_id),
format!("const generic parameter not found in {generics:?} at position {arg_idx:?}"),
);
@@ -311,6 +307,9 @@ fn get_path_containing_arg_in_pat<'hir>(
}
pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty<'_>> {
+ use rustc_hir::*;
+ use rustc_middle::ty::Ty;
+
// If we are computing `type_of` the synthesized associated type for an RPITIT in the impl
// side, use `collect_return_position_impl_trait_in_trait_tys` to infer the value of the
// associated type in the impl.
@@ -323,7 +322,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
return map[&assoc_item.trait_item_def_id.unwrap()];
}
Err(_) => {
- return ty::EarlyBinder(tcx.ty_error_with_message(
+ return ty::EarlyBinder::bind(Ty::new_error_with_message(
+ tcx,
DUMMY_SP,
"Could not collect return position impl trait in trait tys",
));
@@ -331,8 +331,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
}
}
- use rustc_hir::*;
-
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let icx = ItemCtxt::new(tcx, def_id);
@@ -341,13 +339,18 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
Node::TraitItem(item) => match item.kind {
TraitItemKind::Fn(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id.to_def_id(), substs)
+ Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
}
TraitItemKind::Const(ty, body_id) => body_id
.and_then(|body_id| {
is_suggestable_infer_ty(ty).then(|| {
infer_placeholder_type(
- tcx, def_id, body_id, ty.span, item.ident, "constant",
+ tcx,
+ def_id,
+ body_id,
+ ty.span,
+ item.ident,
+ "associated constant",
)
})
})
@@ -361,11 +364,18 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
Node::ImplItem(item) => match item.kind {
ImplItemKind::Fn(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id.to_def_id(), substs)
+ Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
}
ImplItemKind::Const(ty, body_id) => {
if is_suggestable_infer_ty(ty) {
- infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident, "constant")
+ infer_placeholder_type(
+ tcx,
+ def_id,
+ body_id,
+ ty.span,
+ item.ident,
+ "associated constant",
+ )
} else {
icx.to_ty(ty)
}
@@ -411,31 +421,31 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
span: spans.into(),
note: (),
});
- tcx.ty_error(guar)
+ Ty::new_error(tcx, guar)
}
_ => icx.to_ty(*self_ty),
},
ItemKind::Fn(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id.to_def_id(), substs)
+ Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
}
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => {
let def = tcx.adt_def(def_id);
let substs = InternalSubsts::identity_for_item(tcx, def_id);
- tcx.mk_adt(def, substs)
+ Ty::new_adt(tcx, def, substs)
}
ItemKind::OpaqueTy(OpaqueTy {
origin: hir::OpaqueTyOrigin::TyAlias { .. },
..
}) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id),
// Opaque types desugared from `impl Trait`.
- ItemKind::OpaqueTy(OpaqueTy {
+ ItemKind::OpaqueTy(&OpaqueTy {
origin:
hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner),
in_trait,
..
}) => {
- if in_trait && !tcx.impl_defaultness(owner).has_value() {
+ if in_trait && !tcx.defaultness(owner).has_value() {
span_bug!(
tcx.def_span(def_id),
"tried to get type of this RPITIT with no definition"
@@ -463,10 +473,10 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
Node::ForeignItem(foreign_item) => match foreign_item.kind {
ForeignItemKind::Fn(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id.to_def_id(), substs)
+ Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
}
ForeignItemKind::Static(t, _) => icx.to_ty(t),
- ForeignItemKind::Type => tcx.mk_foreign(def_id.to_def_id()),
+ ForeignItemKind::Type => Ty::new_foreign(tcx, def_id.to_def_id()),
},
Node::Ctor(def) | Node::Variant(Variant { data: def, .. }) => match def {
@@ -475,7 +485,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
}
VariantData::Tuple(..) => {
let substs = InternalSubsts::identity_for_item(tcx, def_id);
- tcx.mk_fn_def(def_id.to_def_id(), substs)
+ Ty::new_fn_def(tcx, def_id.to_def_id(), substs)
}
},
@@ -487,6 +497,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
Node::AnonConst(_) => anon_const_type_of(tcx, def_id),
+ Node::ConstBlock(_) => {
+ let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
+ substs.as_inline_const().ty()
+ }
+
Node::GenericParam(param) => match &param.kind {
GenericParamKind::Type { default: Some(ty), .. }
| GenericParamKind::Const { ty, .. } => icx.to_ty(ty),
@@ -497,7 +512,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
bug!("unexpected sort of node in type_of(): {:?}", x);
}
};
- ty::EarlyBinder(output)
+ ty::EarlyBinder::bind(output)
}
fn infer_placeholder_type<'a>(
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 f7c5b4467..957a6bb34 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -1,3 +1,4 @@
+use rustc_errors::StashKey;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem};
@@ -5,7 +6,7 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_span::DUMMY_SP;
-use crate::errors::UnconstrainedOpaqueType;
+use crate::errors::{TaitForwardCompat, UnconstrainedOpaqueType};
/// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions
/// laid for "higher-order pattern unification".
@@ -59,7 +60,20 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
}
}
- let Some(hidden) = locator.found else {
+ if let Some(hidden) = locator.found {
+ // Only check against typeck if we didn't already error
+ if !hidden.ty.references_error() {
+ for concrete_type in locator.typeck_types {
+ if concrete_type.ty != tcx.erase_regions(hidden.ty)
+ && !(concrete_type, hidden).references_error()
+ {
+ hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
+ }
+ }
+ }
+
+ hidden.ty
+ } else {
let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
span: tcx.def_span(def_id),
name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
@@ -70,21 +84,8 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
_ => "item",
},
});
- return tcx.ty_error(reported);
- };
-
- // Only check against typeck if we didn't already error
- if !hidden.ty.references_error() {
- for concrete_type in locator.typeck_types {
- if concrete_type.ty != tcx.erase_regions(hidden.ty)
- && !(concrete_type, hidden).references_error()
- {
- hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
- }
- }
+ Ty::new_error(tcx, reported)
}
-
- hidden.ty
}
struct TaitConstraintLocator<'tcx> {
@@ -127,16 +128,41 @@ impl TaitConstraintLocator<'_> {
// ```
let tables = self.tcx.typeck(item_def_id);
if let Some(guar) = tables.tainted_by_errors {
- self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
+ self.found =
+ Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: Ty::new_error(self.tcx, guar) });
return;
}
- let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
+
+ let mut constrained = false;
+ for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
+ if opaque_type_key.def_id != self.def_id {
+ continue;
+ }
+ constrained = true;
+ if !self.tcx.opaque_types_defined_by(item_def_id).contains(&self.def_id) {
+ self.tcx.sess.emit_err(TaitForwardCompat {
+ span: hidden_type.span,
+ item_span: self
+ .tcx
+ .def_ident_span(item_def_id)
+ .unwrap_or_else(|| self.tcx.def_span(item_def_id)),
+ });
+ }
+ let concrete_type =
+ self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
+ opaque_type_key,
+ self.tcx,
+ true,
+ ));
+ if self.typeck_types.iter().all(|prev| prev.ty != concrete_type.ty) {
+ self.typeck_types.push(concrete_type);
+ }
+ }
+
+ if !constrained {
debug!("no constraints in typeck results");
return;
};
- if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) {
- self.typeck_types.push(typeck_hidden_ty);
- }
// Use borrowck to get the type with unerased regions.
let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
@@ -146,7 +172,7 @@ impl TaitConstraintLocator<'_> {
if let Some(prev) = &mut self.found {
if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
let guar = prev.report_mismatch(&concrete_type, self.def_id, self.tcx).emit();
- prev.ty = self.tcx.ty_error(guar);
+ prev.ty = Ty::new_error(self.tcx, guar);
}
} else {
self.found = Some(concrete_type);
@@ -190,17 +216,45 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
}
}
-pub(super) fn find_opaque_ty_constraints_for_rpit(
- tcx: TyCtxt<'_>,
+pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
+ tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
owner_def_id: LocalDefId,
) -> Ty<'_> {
- let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
+ let tables = tcx.typeck(owner_def_id);
- if let Some(concrete) = concrete {
+ // Check that all of the opaques we inferred during HIR are compatible.
+ // FIXME: We explicitly don't check that the types inferred during HIR
+ // typeck are compatible with the one that we infer during borrowck,
+ // because that one actually sometimes has consts evaluated eagerly so
+ // using strict type equality will fail.
+ let mut hir_opaque_ty: Option<ty::OpaqueHiddenType<'tcx>> = None;
+ if tables.tainted_by_errors.is_none() {
+ for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
+ if opaque_type_key.def_id != def_id {
+ continue;
+ }
+ let concrete_type = tcx.erase_regions(
+ hidden_type.remap_generic_params_to_declaration_params(opaque_type_key, tcx, true),
+ );
+ if let Some(prev) = &mut hir_opaque_ty {
+ if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
+ prev.report_mismatch(&concrete_type, def_id, tcx).stash(
+ tcx.def_span(opaque_type_key.def_id),
+ StashKey::OpaqueHiddenTypeMismatch,
+ );
+ }
+ } else {
+ hir_opaque_ty = Some(concrete_type);
+ }
+ }
+ }
+
+ 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);
debug!(?scope);
- let mut locator = RpitConstraintChecker { def_id, tcx, found: concrete };
+ let mut locator = RpitConstraintChecker { def_id, tcx, found: mir_opaque_ty };
match tcx.hir().get(scope) {
Node::Item(it) => intravisit::walk_item(&mut locator, it),
@@ -208,27 +262,28 @@ pub(super) fn find_opaque_ty_constraints_for_rpit(
Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
other => bug!("{:?} is not a valid scope for an opaque type item", other),
}
- }
- concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
- let table = tcx.typeck(owner_def_id);
- if let Some(guar) = table.tainted_by_errors {
- // Some error in the
- // owner fn prevented us from populating
+ mir_opaque_ty.ty
+ } else {
+ if let Some(guar) = tables.tainted_by_errors {
+ // Some error in the owner fn prevented us from populating
// the `concrete_opaque_types` table.
- tcx.ty_error(guar)
+ Ty::new_error(tcx, guar)
} else {
- table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
+ // Fall back to the RPIT we inferred during HIR typeck
+ if let Some(hir_opaque_ty) = hir_opaque_ty {
+ hir_opaque_ty.ty
+ } else {
// We failed to resolve the opaque type or it
// resolves to itself. We interpret this as the
// no values of the hidden type ever being constructed,
// so we can just make the hidden type be `!`.
// For backwards compatibility reasons, we fall back to
// `()` until we the diverging default is changed.
- tcx.mk_diverging_default()
- })
+ Ty::new_diverging_default(tcx)
+ }
}
- })
+ }
}
struct RpitConstraintChecker<'tcx> {
diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
index 9200c2aec..35882ad35 100644
--- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
+++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs
@@ -151,7 +151,7 @@ pub fn identify_constrained_generic_params<'tcx>(
/// think of any.
pub fn setup_constraining_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
- predicates: &mut [(ty::Predicate<'tcx>, Span)],
+ predicates: &mut [(ty::Clause<'tcx>, Span)],
impl_trait_ref: Option<ty::TraitRef<'tcx>>,
input_parameters: &mut FxHashSet<Parameter>,
) {
@@ -187,9 +187,7 @@ pub fn setup_constraining_predicates<'tcx>(
for j in i..predicates.len() {
// Note that we don't have to care about binders here,
// as the impl trait ref never contains any late-bound regions.
- if let ty::PredicateKind::Clause(ty::Clause::Projection(projection)) =
- predicates[j].0.kind().skip_binder()
- {
+ if let ty::ClauseKind::Projection(projection) = predicates[j].0.kind().skip_binder() {
// Special case: watch out for some kind of sneaky attempt
// to project out an associated type defined by this very
// trait.
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 6e7eb4f6c..c2d2e5f7e 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -5,7 +5,7 @@ use rustc_errors::{
error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed, Handler, IntoDiagnostic,
MultiSpan,
};
-use rustc_macros::{Diagnostic, Subdiagnostic};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_middle::ty::{self, print::TraitRefPrintOnlyTraitPath, Ty};
use rustc_span::{symbol::Ident, Span, Symbol};
@@ -184,6 +184,16 @@ pub struct UnconstrainedOpaqueType {
pub what: &'static str,
}
+#[derive(Diagnostic)]
+#[diag(hir_analysis_tait_forward_compat)]
+#[note]
+pub struct TaitForwardCompat {
+ #[primary_span]
+ pub span: Span,
+ #[note]
+ pub item_span: Span,
+}
+
pub struct MissingTypeParams {
pub span: Span,
pub def_span: Span,
@@ -857,3 +867,54 @@ pub(crate) enum DropImplPolarity {
span: Span,
},
}
+
+#[derive(Diagnostic)]
+pub(crate) enum ReturnTypeNotationIllegalParam {
+ #[diag(hir_analysis_return_type_notation_illegal_param_type)]
+ Type {
+ #[primary_span]
+ span: Span,
+ #[label]
+ param_span: Span,
+ },
+ #[diag(hir_analysis_return_type_notation_illegal_param_const)]
+ Const {
+ #[primary_span]
+ span: Span,
+ #[label]
+ param_span: Span,
+ },
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum LateBoundInApit {
+ #[diag(hir_analysis_late_bound_type_in_apit)]
+ Type {
+ #[primary_span]
+ span: Span,
+ #[label]
+ param_span: Span,
+ },
+ #[diag(hir_analysis_late_bound_const_in_apit)]
+ Const {
+ #[primary_span]
+ span: Span,
+ #[label]
+ param_span: Span,
+ },
+ #[diag(hir_analysis_late_bound_lifetime_in_apit)]
+ Lifetime {
+ #[primary_span]
+ span: Span,
+ #[label]
+ param_span: Span,
+ },
+}
+
+#[derive(LintDiagnostic)]
+#[diag(hir_analysis_unused_associated_type_bounds)]
+#[note]
+pub struct UnusedAssociatedTypeBounds {
+ #[suggestion(code = "")]
+ pub span: Span,
+}
diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
index e4c6e6e39..f1765174d 100644
--- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs
@@ -79,7 +79,7 @@ fn diagnostic_hir_wf_check<'tcx>(
self.tcx,
cause,
self.param_env,
- ty::PredicateKind::WellFormed(tcx_ty.into()),
+ ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(tcx_ty.into())),
));
for error in ocx.select_all_or_error() {
@@ -128,7 +128,9 @@ fn diagnostic_hir_wf_check<'tcx>(
ref item => bug!("Unexpected TraitItem {:?}", item),
},
hir::Node::Item(item) => match item.kind {
- hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _) => vec![ty],
+ hir::ItemKind::TyAlias(ty, _)
+ | hir::ItemKind::Static(ty, _, _)
+ | hir::ItemKind::Const(ty, _) => vec![ty],
hir::ItemKind::Impl(impl_) => match &impl_.of_trait {
Some(t) => t
.path
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 612d4ff3d..5526dd4b0 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -106,10 +106,23 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
if item.defaultness(tcx).has_value() {
cgp::parameters_for(&tcx.type_of(def_id).subst_identity(), true)
} else {
- Vec::new()
+ vec![]
}
}
- ty::AssocKind::Fn | ty::AssocKind::Const => Vec::new(),
+ ty::AssocKind::Fn => {
+ if !tcx.lower_impl_trait_in_trait_to_assoc_ty()
+ && item.defaultness(tcx).has_value()
+ && tcx.impl_method_has_trait_impl_trait_tys(item.def_id)
+ && let Ok(table) = tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
+ {
+ table.values().copied().flat_map(|ty| {
+ cgp::parameters_for(&ty.subst_identity(), true)
+ }).collect()
+ } else {
+ vec![]
+ }
+ }
+ ty::AssocKind::Const => vec![],
}
})
.collect();
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
index e84da2519..c64fb469b 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs
@@ -77,7 +77,7 @@ use rustc_infer::traits::specialization_graph::Node;
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
-use rustc_span::Span;
+use rustc_span::{ErrorGuaranteed, Span};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{self, translate_substs_with_cause, wf, ObligationCtxt};
@@ -113,7 +113,7 @@ fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node
let span = tcx.def_span(impl1_def_id);
check_has_items(tcx, impl1_def_id, impl2_node, span);
- if let Some((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) {
+ if let Ok((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) {
let impl2_def_id = impl2_node.def_id();
debug!(?impl2_def_id, ?impl2_substs);
@@ -171,16 +171,14 @@ fn get_impl_substs(
tcx: TyCtxt<'_>,
impl1_def_id: LocalDefId,
impl2_node: Node,
-) -> Option<(SubstsRef<'_>, SubstsRef<'_>)> {
+) -> Result<(SubstsRef<'_>, SubstsRef<'_>), ErrorGuaranteed> {
let infcx = &tcx.infer_ctxt().build();
let ocx = ObligationCtxt::new(infcx);
let param_env = tcx.param_env(impl1_def_id);
-
- let assumed_wf_types =
- ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id);
+ let impl1_span = tcx.def_span(impl1_def_id);
+ let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?;
let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
- let impl1_span = tcx.def_span(impl1_def_id);
let impl2_substs = translate_substs_with_cause(
infcx,
param_env,
@@ -198,8 +196,8 @@ fn get_impl_substs(
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
- ocx.infcx.err_ctxt().report_fulfillment_errors(&errors);
- return None;
+ let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(&errors);
+ return Err(guar);
}
let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types);
@@ -207,10 +205,10 @@ fn get_impl_substs(
let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
let span = tcx.def_span(impl1_def_id);
- tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
- return None;
+ let guar = tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
+ return Err(guar);
};
- Some((impl1_substs, impl2_substs))
+ Ok((impl1_substs, impl2_substs))
}
/// Returns a list of all of the unconstrained subst of the given impl.
@@ -235,10 +233,8 @@ fn unconstrained_parent_impl_substs<'tcx>(
// what we want here. We want only a list of constrained parameters while
// the functions in `cgp` add the constrained parameters to a list of
// unconstrained parameters.
- for (predicate, _) in impl_generic_predicates.predicates.iter() {
- if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) =
- predicate.kind().skip_binder()
- {
+ for (clause, _) in impl_generic_predicates.predicates.iter() {
+ if let ty::ClauseKind::Projection(proj) = clause.kind().skip_binder() {
let projection_ty = proj.projection_ty;
let projected_ty = proj.term;
@@ -340,8 +336,11 @@ fn check_predicates<'tcx>(
impl2_substs: SubstsRef<'tcx>,
span: Span,
) {
- let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
- let impl1_predicates: Vec<_> = traits::elaborate(tcx, instantiated.into_iter()).collect();
+ let impl1_predicates: Vec<_> = traits::elaborate(
+ tcx,
+ tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs).into_iter(),
+ )
+ .collect();
let mut impl2_predicates = if impl2_node.is_from_trait() {
// Always applicable traits have to be always applicable without any
@@ -352,8 +351,8 @@ fn check_predicates<'tcx>(
tcx,
tcx.predicates_of(impl2_node.def_id())
.instantiate(tcx, impl2_substs)
- .predicates
- .into_iter(),
+ .into_iter()
+ .map(|(c, _s)| c.as_predicate()),
)
.collect()
};
@@ -377,13 +376,13 @@ fn check_predicates<'tcx>(
let always_applicable_traits = impl1_predicates
.iter()
.copied()
- .filter(|&(predicate, _)| {
+ .filter(|(clause, _span)| {
matches!(
- trait_predicate_kind(tcx, predicate),
+ trait_predicate_kind(tcx, clause.as_predicate()),
Some(TraitSpecializationKind::AlwaysApplicable)
)
})
- .map(|(pred, _span)| pred);
+ .map(|(c, _span)| c.as_predicate());
// Include the well-formed predicates of the type parameters of the impl.
for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().subst_identity().substs {
@@ -398,9 +397,12 @@ fn check_predicates<'tcx>(
}
impl2_predicates.extend(traits::elaborate(tcx, always_applicable_traits));
- for (predicate, span) in impl1_predicates {
- if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(tcx, predicate, *pred2, span)) {
- check_specialization_on(tcx, predicate, span)
+ for (clause, span) in impl1_predicates {
+ if !impl2_predicates
+ .iter()
+ .any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span))
+ {
+ check_specialization_on(tcx, clause.as_predicate(), span)
}
}
}
@@ -438,8 +440,8 @@ fn trait_predicates_eq<'tcx>(
let pred2_kind = predicate2.kind().skip_binder();
let (trait_pred1, trait_pred2) = match (pred1_kind, pred2_kind) {
(
- ty::PredicateKind::Clause(ty::Clause::Trait(pred1)),
- ty::PredicateKind::Clause(ty::Clause::Trait(pred2)),
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred1)),
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred2)),
) => (pred1, pred2),
// Just use plain syntactic equivalence if either of the predicates aren't
// trait predicates or have bound vars.
@@ -478,7 +480,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
_ if predicate.is_global() => (),
// We allow specializing on explicitly marked traits with no associated
// items.
- ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
constness: _,
polarity: _,
@@ -498,7 +500,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
.emit();
}
}
- ty::PredicateKind::Clause(ty::Clause::Projection(ty::ProjectionPredicate {
+ ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_ty,
term,
})) => {
@@ -509,7 +511,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
)
.emit();
}
- ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => {
+ ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => {
// FIXME(min_specialization), FIXME(const_generics):
// It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure
// about the actual rules that would be sound. Can't just always error here because otherwise
@@ -532,24 +534,23 @@ fn trait_predicate_kind<'tcx>(
predicate: ty::Predicate<'tcx>,
) -> Option<TraitSpecializationKind> {
match predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
+ ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
constness: _,
polarity: _,
})) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind),
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(_))
- | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_))
- | ty::PredicateKind::Clause(ty::Clause::Projection(_))
- | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
+ ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_))
+ | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(_))
+ | ty::PredicateKind::Clause(ty::ClauseKind::Projection(_))
+ | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
| ty::PredicateKind::AliasRelate(..)
- | ty::PredicateKind::WellFormed(_)
+ | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_))
| ty::PredicateKind::Subtype(_)
| ty::PredicateKind::Coerce(_)
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(..)
- | ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::ConstEquate(..)
- | ty::PredicateKind::Ambiguous
- | ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
+ | ty::PredicateKind::Ambiguous => None,
}
}
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 5cd2cd50c..a68832d96 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -59,8 +59,6 @@ This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(box_patterns)]
#![feature(control_flow_enum)]
-#![feature(drain_filter)]
-#![feature(hash_drain_filter)]
#![feature(if_let_guard)]
#![feature(is_sorted)]
#![feature(iter_intersperse)]
@@ -321,16 +319,19 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
expected_return_type = main_fnsig.output();
} else {
// standard () main return type
- expected_return_type = ty::Binder::dummy(tcx.mk_unit());
+ expected_return_type = ty::Binder::dummy(Ty::new_unit(tcx));
}
if error {
return;
}
- let se_ty = tcx.mk_fn_ptr(expected_return_type.map_bound(|expected_return_type| {
- tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
- }));
+ let se_ty = Ty::new_fn_ptr(
+ tcx,
+ expected_return_type.map_bound(|expected_return_type| {
+ tcx.mk_fn_sig([], expected_return_type, false, hir::Unsafety::Normal, Abi::Rust)
+ }),
+ );
require_same_types(
tcx,
@@ -341,7 +342,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
),
param_env,
se_ty,
- tcx.mk_fn_ptr(main_fnsig),
+ Ty::new_fn_ptr(tcx, main_fnsig),
);
}
fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
@@ -399,13 +400,16 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
}
}
- let se_ty = tcx.mk_fn_ptr(ty::Binder::dummy(tcx.mk_fn_sig(
- [tcx.types.isize, tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))],
- tcx.types.isize,
- false,
- hir::Unsafety::Normal,
- Abi::Rust,
- )));
+ let se_ty = Ty::new_fn_ptr(
+ tcx,
+ ty::Binder::dummy(tcx.mk_fn_sig(
+ [tcx.types.isize, Ty::new_imm_ptr(tcx, Ty::new_imm_ptr(tcx, tcx.types.u8))],
+ tcx.types.isize,
+ false,
+ hir::Unsafety::Normal,
+ Abi::Rust,
+ )),
+ );
require_same_types(
tcx,
@@ -416,7 +420,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) {
),
ty::ParamEnv::empty(), // start should not have any where bounds.
se_ty,
- tcx.mk_fn_ptr(tcx.fn_sig(start_def_id).subst_identity()),
+ Ty::new_fn_ptr(tcx, tcx.fn_sig(start_def_id).subst_identity()),
);
}
_ => {
diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
index 357deb07b..a7fca41f8 100644
--- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs
@@ -30,45 +30,34 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
// process predicates and convert to `RequiredPredicates` entry, see below
for &(predicate, span) in predicates.predicates {
match predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(OutlivesPredicate(
- ty,
- reg,
- ))) => insert_outlives_predicate(
- tcx,
- ty.into(),
- reg,
- span,
- &mut required_predicates,
- ),
-
- ty::PredicateKind::Clause(ty::Clause::RegionOutlives(OutlivesPredicate(
- reg1,
- reg2,
- ))) => insert_outlives_predicate(
- tcx,
- reg1.into(),
- reg2,
- span,
- &mut required_predicates,
- ),
-
- ty::PredicateKind::Clause(ty::Clause::Trait(..))
- | ty::PredicateKind::Clause(ty::Clause::Projection(..))
- | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..))
- | 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::Ambiguous
- | ty::PredicateKind::TypeWellFormedFromEnv(..) => (),
+ ty::ClauseKind::TypeOutlives(OutlivesPredicate(ty, reg)) => {
+ insert_outlives_predicate(
+ tcx,
+ ty.into(),
+ reg,
+ span,
+ &mut required_predicates,
+ )
+ }
+
+ ty::ClauseKind::RegionOutlives(OutlivesPredicate(reg1, reg2)) => {
+ insert_outlives_predicate(
+ tcx,
+ reg1.into(),
+ reg2,
+ span,
+ &mut required_predicates,
+ )
+ }
+ ty::ClauseKind::Trait(_)
+ | ty::ClauseKind::Projection(_)
+ | ty::ClauseKind::ConstArgHasType(_, _)
+ | ty::ClauseKind::WellFormed(_)
+ | ty::ClauseKind::ConstEvaluatable(_) => {}
}
}
- ty::EarlyBinder(required_predicates)
+ ty::EarlyBinder::bind(required_predicates)
})
}
}
diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
index 0cd2fc1aa..71dca918f 100644
--- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs
@@ -68,12 +68,13 @@ pub(super) fn infer_predicates(
// Therefore mark `predicates_added` as true and which will ensure
// we walk the crates again and re-calculate predicates for all
// items.
- let item_predicates_len: usize =
- global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.0.len());
+ let item_predicates_len: usize = global_inferred_outlives
+ .get(&item_did.to_def_id())
+ .map_or(0, |p| p.as_ref().skip_binder().len());
if item_required_predicates.len() > item_predicates_len {
predicates_added = true;
global_inferred_outlives
- .insert(item_did.to_def_id(), ty::EarlyBinder(item_required_predicates));
+ .insert(item_did.to_def_id(), ty::EarlyBinder::bind(item_required_predicates));
}
}
@@ -137,7 +138,9 @@ fn insert_required_predicates_to_be_wf<'tcx>(
// 'a` holds for `Foo`.
debug!("Adt");
if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did()) {
- for (unsubstituted_predicate, &span) in &unsubstituted_predicates.0 {
+ for (unsubstituted_predicate, &span) in
+ unsubstituted_predicates.as_ref().skip_binder()
+ {
// `unsubstituted_predicate` is `U: 'b` in the
// example above. So apply the substitution to
// get `T: 'a` (or `predicate`):
@@ -251,7 +254,7 @@ fn check_explicit_predicates<'tcx>(
);
let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id);
- for (outlives_predicate, &span) in &explicit_predicates.0 {
+ for (outlives_predicate, &span) in explicit_predicates.as_ref().skip_binder() {
debug!("outlives_predicate = {:?}", &outlives_predicate);
// Careful: If we are inferring the effects of a `dyn Trait<..>`
diff --git a/compiler/rustc_hir_analysis/src/outlives/mod.rs b/compiler/rustc_hir_analysis/src/outlives/mod.rs
index a8596c707..48624cefe 100644
--- a/compiler/rustc_hir_analysis/src/outlives/mod.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/mod.rs
@@ -3,7 +3,7 @@ use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::query::Providers;
use rustc_middle::ty::subst::GenericArgKind;
-use rustc_middle::ty::{self, CratePredicatesMap, TyCtxt};
+use rustc_middle::ty::{self, CratePredicatesMap, ToPredicate, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::Span;
@@ -20,7 +20,8 @@ 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);
- if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst) && tcx.lazy_normalization()
+ if matches!(tcx.def_kind(item_def_id), hir::def::DefKind::AnonConst)
+ && tcx.features().generic_const_exprs
{
if tcx.hir().opt_const_param_default_param_def_id(id).is_some() {
// In `generics_of` we set the generics' parent to be our parent's parent which means that
@@ -51,9 +52,9 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau
if tcx.has_attr(item_def_id, sym::rustc_outlives) {
let mut pred: Vec<String> = predicates
.iter()
- .map(|(out_pred, _)| match out_pred {
- ty::Clause::RegionOutlives(p) => p.to_string(),
- ty::Clause::TypeOutlives(p) => p.to_string(),
+ .map(|(out_pred, _)| match out_pred.kind().skip_binder() {
+ ty::ClauseKind::RegionOutlives(p) => p.to_string(),
+ ty::ClauseKind::TypeOutlives(p) => p.to_string(),
err => bug!("unexpected clause {:?}", err),
})
.collect();
@@ -98,24 +99,29 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
let predicates = global_inferred_outlives
.iter()
.map(|(&def_id, set)| {
- let predicates = &*tcx.arena.alloc_from_iter(set.0.iter().filter_map(
- |(ty::OutlivesPredicate(kind1, region2), &span)| {
- match kind1.unpack() {
- GenericArgKind::Type(ty1) => Some((
- ty::Clause::TypeOutlives(ty::OutlivesPredicate(ty1, *region2)),
- span,
- )),
- GenericArgKind::Lifetime(region1) => Some((
- ty::Clause::RegionOutlives(ty::OutlivesPredicate(region1, *region2)),
- span,
- )),
- GenericArgKind::Const(_) => {
- // Generic consts don't impose any constraints.
- None
+ let predicates =
+ &*tcx.arena.alloc_from_iter(set.as_ref().skip_binder().iter().filter_map(
+ |(ty::OutlivesPredicate(kind1, region2), &span)| {
+ match kind1.unpack() {
+ GenericArgKind::Type(ty1) => Some((
+ ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty1, *region2))
+ .to_predicate(tcx),
+ span,
+ )),
+ GenericArgKind::Lifetime(region1) => Some((
+ ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(
+ region1, *region2,
+ ))
+ .to_predicate(tcx),
+ span,
+ )),
+ GenericArgKind::Const(_) => {
+ // Generic consts don't impose any constraints.
+ None
+ }
}
- }
- },
- ));
+ },
+ ));
(def_id, predicates)
})
.collect();
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 3ebd9e134..066e74491 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -51,20 +51,19 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
| DefKind::Struct
| DefKind::Union
| DefKind::Variant
- | DefKind::Ctor(..) => {}
+ | DefKind::Ctor(..) => {
+ // These are inferred.
+ let crate_map = tcx.crate_variances(());
+ return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
+ }
DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => {
return variance_of_opaque(tcx, item_def_id);
}
- _ => {
- // Variance not relevant.
- span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item")
- }
+ _ => {}
}
- // Everything else must be inferred.
-
- let crate_map = tcx.crate_variances(());
- crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[])
+ // Variance not relevant.
+ span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item");
}
#[instrument(level = "trace", skip(tcx), ret)]
@@ -119,7 +118,8 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary
// at all for RPITITs.
ty::Alias(_, ty::AliasTy { def_id, substs, .. })
- if self.tcx.is_impl_trait_in_trait(*def_id) =>
+ if self.tcx.is_impl_trait_in_trait(*def_id)
+ && !self.tcx.lower_impl_trait_in_trait_to_assoc_ty() =>
{
self.visit_opaque(*def_id, substs)
}
@@ -162,28 +162,25 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
// which thus mentions `'a` and should thus accept hidden types that borrow 'a
// instead of requiring an additional `+ 'a`.
match pred.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
+ ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref: ty::TraitRef { def_id: _, substs, .. },
constness: _,
polarity: _,
- })) => {
+ }) => {
for subst in &substs[1..] {
subst.visit_with(&mut collector);
}
}
- ty::PredicateKind::Clause(ty::Clause::Projection(ty::ProjectionPredicate {
+ ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_ty: ty::AliasTy { substs, .. },
term,
- })) => {
+ }) => {
for subst in &substs[1..] {
subst.visit_with(&mut collector);
}
term.visit_with(&mut collector);
}
- ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
- _,
- region,
- ))) => {
+ ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(_, region)) => {
region.visit_with(&mut collector);
}
_ => {