diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
11 files changed, 196 insertions, 217 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index e6465d641f1..5368dc0735b 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -267,7 +267,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // segments, even though `trait_ref.path.segments` is of length `1`. Work // around that bug here, even though it should be fixed elsewhere. // This would otherwise cause an invalid suggestion. For an example, look at - // `src/test/ui/issues/issue-28344.rs` where instead of the following: + // `tests/ui/issues/issue-28344.rs` where instead of the following: // // error[E0191]: the value of the associated type `Output` // (from trait `std::ops::BitXor`) must be specified diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index b6e6f7004e7..5a7957be318 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -106,11 +106,12 @@ pub trait AstConv<'tcx> { poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx>; - /// Normalize an associated type coming from the user. - /// - /// This should only be used by astconv. Use `FnCtxt::normalize` - /// or `ObligationCtxt::normalize` in downstream crates. - fn normalize_ty(&self, span: Span, ty: Ty<'tcx>) -> Ty<'tcx>; + /// Returns `AdtDef` if `ty` is an ADT. + /// Note that `ty` might be a projection type that needs normalization. + /// This used to get the enum variants in scope of the type. + /// For example, `Self::A` could refer to an associated type + /// or to an enum variant depending on the result of this function. + fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>>; /// Invoked when we encounter an error from some prior pass /// (e.g., resolve) that is translated into a ty-error. This is @@ -485,14 +486,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Avoid ICE #86756 when type error recovery goes awry. return tcx.ty_error().into(); } - self.astconv - .normalize_ty( - self.span, - tcx.at(self.span) - .bound_type_of(param.def_id) - .subst(tcx, substs), - ) - .into() + tcx.at(self.span).bound_type_of(param.def_id).subst(tcx, substs).into() } else if infer_args { self.astconv.ty_infer(Some(param), self.span).into() } else { @@ -682,7 +676,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty::Binder::bind_with_vars(tcx.mk_trait_ref(trait_def_id, substs), bound_vars); debug!(?poly_trait_ref, ?assoc_bindings); - bounds.trait_bounds.push((poly_trait_ref, span, constness)); + bounds.push_trait_bound(tcx, poly_trait_ref, span, constness); let mut dup_bindings = FxHashMap::default(); for binding in &assoc_bindings { @@ -853,18 +847,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } /// Sets `implicitly_sized` to true on `Bounds` if necessary - pub(crate) fn add_implicitly_sized<'hir>( + pub(crate) fn add_implicitly_sized( &self, - bounds: &mut Bounds<'hir>, - ast_bounds: &'hir [hir::GenericBound<'hir>], - self_ty_where_predicates: Option<(LocalDefId, &'hir [hir::WherePredicate<'hir>])>, + 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: &'hir [hir::GenericBound<'hir>]| { + 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() { @@ -912,7 +907,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // No lang item for `Sized`, so we can't add it as a bound. return; } - bounds.implicitly_sized = Some(span); + bounds.push_sized(tcx, self_ty, span); } /// This helper takes a *converted* parameter type (`param_ty`) @@ -963,10 +958,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::GenericBound::Outlives(lifetime) => { let region = self.ast_region_to_region(lifetime, None); - bounds.region_bounds.push(( - ty::Binder::bind_with_vars(region, bound_vars), + bounds.push_region_bound( + self.tcx(), + ty::Binder::bind_with_vars( + ty::OutlivesPredicate(param_ty, region), + bound_vars, + ), lifetime.ident.span, - )); + ); } } } @@ -1234,13 +1233,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; } } - bounds.projection_bounds.push(( - projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate { - projection_ty, - term: term, - }), + 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 @@ -1263,13 +1261,13 @@ 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.normalize_ty(span, self.tcx().at(span).bound_type_of(did).subst(self.tcx(), substs)) + self.tcx().at(span).bound_type_of(did).subst(self.tcx(), substs) } fn conv_object_ty_poly_trait_ref( &self, span: Span, - trait_bounds: &[hir::PolyTraitRef<'_>], + hir_trait_bounds: &[hir::PolyTraitRef<'_>], lifetime: &hir::Lifetime, borrowed: bool, representation: DynKind, @@ -1279,7 +1277,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { 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 trait_bounds.iter().rev() { + for trait_bound in hir_trait_bounds.iter().rev() { if let GenericArgCountResult { correct: Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }), @@ -1296,10 +1294,45 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } + 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(_) => bug!(), + }, + ty::PredicateKind::WellFormed(_) + | 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, bounds.trait_bounds.iter().map(|&(a, b, _)| (a, b))); + 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())); @@ -1336,8 +1369,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if regular_traits.is_empty() && auto_traits.is_empty() { - let trait_alias_span = bounds - .trait_bounds + let trait_alias_span = trait_bounds .iter() .map(|&(trait_ref, _, _)| trait_ref.def_id()) .find(|&trait_ref| tcx.is_trait_alias(trait_ref)) @@ -1368,8 +1400,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Use a `BTreeSet` to keep output in a more consistent order. let mut associated_types: FxHashMap<Span, BTreeSet<DefId>> = FxHashMap::default(); - let regular_traits_refs_spans = bounds - .trait_bounds + let regular_traits_refs_spans = trait_bounds .into_iter() .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id())); @@ -1423,7 +1454,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // the discussion in #56288 for alternatives. if !references_self { // Include projections defined on supertraits. - bounds.projection_bounds.push((pred, span)); + projection_bounds.push((pred, span)); } } _ => (), @@ -1431,7 +1462,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - for (projection_bound, _) in &bounds.projection_bounds { + for (projection_bound, _) in &projection_bounds { for def_ids in associated_types.values_mut() { def_ids.remove(&projection_bound.projection_def_id()); } @@ -1440,7 +1471,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.complain_about_missing_associated_types( associated_types, potential_assoc_types, - trait_bounds, + hir_trait_bounds, ); // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as @@ -1482,7 +1513,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let substs = tcx.intern_substs(&substs[..]); let span = i.bottom().1; - let empty_generic_args = trait_bounds.iter().any(|hir_bound| { + 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) }); @@ -1514,7 +1545,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) }); - let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| { + let existential_projections = projection_bounds.iter().map(|(bound, _)| { bound.map_bound(|mut b| { assert_eq!(b.projection_ty.self_ty(), dummy_self); @@ -1795,7 +1826,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { Ok(bound) } - // Create a type from a path to an associated type. + // Create a type from a path to an associated type or to an enum variant. // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C` // and item_segment is the path segment for `D`. We return a type and a def for // the whole path. @@ -1823,7 +1854,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Check if we have an enum variant. let mut variant_resolution = None; - if let ty::Adt(adt_def, adt_substs) = qself_ty.kind() { + if let Some(adt_def) = self.probe_adt(span, qself_ty) { if adt_def.is_enum() { let variant_def = adt_def .variants() @@ -1925,6 +1956,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let Some(assoc_ty_did) = self.lookup_assoc_ty(assoc_ident, hir_ref_id, span, impl_) else { continue; }; + let ty::Adt(_, adt_substs) = qself_ty.kind() else { + // FIXME(inherent_associated_types) + bug!("unimplemented: non-adt self of inherent assoc ty"); + }; let item_substs = self.create_substs_for_associated_item( span, assoc_ty_did, @@ -1932,7 +1967,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { adt_substs, ); let ty = tcx.bound_type_of(assoc_ty_did).subst(tcx, item_substs); - let ty = self.normalize_ty(span, ty); return Ok((ty, DefKind::AssocTy, assoc_ty_did)); } } @@ -2029,7 +2063,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; let ty = self.projected_ty_from_poly_trait_ref(span, assoc_ty_did, assoc_segment, bound); - let ty = self.normalize_ty(span, ty); if let Some(variant_def_id) = variant_resolution { tcx.struct_span_lint_hir( @@ -2165,7 +2198,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { debug!("qpath_to_ty: trait_ref={:?}", trait_ref); - self.normalize_ty(span, tcx.mk_projection(item_def_id, item_substs)) + tcx.mk_projection(item_def_id, item_substs) } pub fn prohibit_generics<'a>( @@ -2282,6 +2315,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Option<Ty<'tcx>>, kind: DefKind, def_id: DefId, + span: Span, ) -> Vec<PathSeg> { // We need to extract the type parameters supplied by the user in // the path `path`. Due to the current setup, this is a bit of a @@ -2349,8 +2383,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Case 2. Reference to a variant constructor. DefKind::Ctor(CtorOf::Variant, ..) | DefKind::Variant => { - let adt_def = self_ty.map(|t| t.ty_adt_def().unwrap()); - let (generics_def_id, index) = if let Some(adt_def) = adt_def { + let (generics_def_id, index) = if let Some(self_ty) = self_ty { + let adt_def = self.probe_adt(span, self_ty).unwrap(); debug_assert!(adt_def.is_enum()); (adt_def.did(), last) } else if last >= 1 && segments[last - 1].args.is_some() { @@ -2426,7 +2460,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); - self.normalize_ty(span, tcx.mk_opaque(did, substs)) + tcx.mk_opaque(did, substs) } Res::Def( DefKind::Enum @@ -2446,7 +2480,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assert_eq!(opt_self_ty, None); let path_segs = - self.def_ids_for_value_path_segments(path.segments, None, kind, def_id); + self.def_ids_for_value_path_segments(path.segments, None, kind, def_id, span); let generic_segs: FxHashSet<_> = path_segs.iter().map(|PathSeg(_, index)| index).collect(); self.prohibit_generics( @@ -2586,7 +2620,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } tcx.ty_error_with_guaranteed(err.emit()) } else { - self.normalize_ty(span, ty) + ty } } Res::Def(DefKind::AssocTy, def_id) => { @@ -2729,8 +2763,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { None, ty::BoundConstness::NotConst, ); - EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id))) - .subst(tcx, substs) + EarlyBinder(tcx.at(span).type_of(def_id)).subst(tcx, substs) } hir::TyKind::Array(ref ty, ref length) => { let length = match length { @@ -2740,8 +2773,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }; - let array_ty = tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length)); - self.normalize_ty(ast_ty.span, array_ty) + tcx.mk_ty(ty::Array(self.ast_ty_to_ty(ty), length)) } hir::TyKind::Typeof(ref e) => { let ty_erased = tcx.type_of(e.def_id); diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index 3e3544ce666..0880c8c15f2 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -1,6 +1,7 @@ //! Bounds are restrictions applied to some types after they've been converted into the //! `ty` form from the HIR. +use rustc_hir::LangItem; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; @@ -15,73 +16,53 @@ use rustc_span::Span; /// ^^^^^^^^^ bounding the type parameter `T` /// /// impl dyn Bar + Baz -/// ^^^^^^^^^ bounding the forgotten dynamic type +/// ^^^^^^^^^ bounding the type-erased dynamic type /// ``` /// /// Our representation is a bit mixed here -- in some cases, we /// include the self type (e.g., `trait_bounds`) but in others we do not #[derive(Default, PartialEq, Eq, Clone, Debug)] pub struct Bounds<'tcx> { - /// A list of region bounds on the (implicit) self type. So if you - /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but - /// the `T` is not explicitly included). - pub region_bounds: Vec<(ty::Binder<'tcx, ty::Region<'tcx>>, Span)>, - - /// A list of trait bounds. So if you had `T: Debug` this would be - /// `T: Debug`. Note that the self-type is explicit here. - pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, ty::BoundConstness)>, - - /// A list of projection equality bounds. So if you had `T: - /// Iterator<Item = u32>` this would include `<T as - /// Iterator>::Item => u32`. Note that the self-type is explicit - /// here. - pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>, - - /// `Some` if there is *no* `?Sized` predicate. The `span` - /// is the location in the source of the `T` declaration which can - /// be cited as the source of the `T: Sized` requirement. - pub implicitly_sized: Option<Span>, + pub predicates: Vec<(ty::Predicate<'tcx>, Span)>, } impl<'tcx> Bounds<'tcx> { - /// Converts a bounds list into a flat set of predicates (like - /// where-clauses). Because some of our bounds listings (e.g., - /// regions) don't include the self-type, you must supply the - /// self-type here (the `param_ty` parameter). - pub fn predicates<'out, 's>( - &'s self, + pub fn push_region_bound( + &mut self, tcx: TyCtxt<'tcx>, - param_ty: Ty<'tcx>, - // the output must live shorter than the duration of the borrow of self and 'tcx. - ) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> + 'out - where - 'tcx: 'out, - 's: 'out, - { - // If it could be sized, and is, add the `Sized` predicate. - let sized_predicate = self.implicitly_sized.and_then(|span| { - // FIXME: use tcx.at(span).mk_trait_ref(LangItem::Sized) here? This may make no-core code harder to write. - let sized = tcx.lang_items().sized_trait()?; - let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(sized, [param_ty])); - Some((trait_ref.without_const().to_predicate(tcx), span)) - }); + region: ty::PolyTypeOutlivesPredicate<'tcx>, + span: Span, + ) { + self.predicates.push((region.to_predicate(tcx), span)); + } - let region_preds = self.region_bounds.iter().map(move |&(region_bound, span)| { - let pred = region_bound - .map_bound(|region_bound| ty::OutlivesPredicate(param_ty, region_bound)) - .to_predicate(tcx); - (pred, span) - }); - let trait_bounds = - self.trait_bounds.iter().map(move |&(bound_trait_ref, span, constness)| { - let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx); - (predicate, span) - }); - let projection_bounds = self - .projection_bounds - .iter() - .map(move |&(projection, span)| (projection.to_predicate(tcx), span)); + pub fn push_trait_bound( + &mut self, + tcx: TyCtxt<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + span: Span, + constness: ty::BoundConstness, + ) { + self.predicates.push((trait_ref.with_constness(constness).to_predicate(tcx), span)); + } + + pub fn push_projection_bound( + &mut self, + tcx: TyCtxt<'tcx>, + projection: ty::PolyProjectionPredicate<'tcx>, + span: Span, + ) { + self.predicates.push((projection.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::Binder::dummy(tcx.mk_trait_ref(sized_def_id, [ty])); + // Preferrable 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)); + } - sized_predicate.into_iter().chain(region_preds).chain(trait_bounds).chain(projection_bounds) + pub fn predicates(&self) -> impl Iterator<Item = (ty::Predicate<'tcx>, Span)> + '_ { + self.predicates.iter().cloned() } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 28cd18bbb8e..43795cfba3f 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -468,14 +468,14 @@ fn check_opaque_meets_bounds<'tcx>( // Can have different predicates to their defining use hir::OpaqueTyOrigin::TyAlias => { let outlives_environment = OutlivesEnvironment::new(param_env); - let _ = infcx.check_region_obligations_and_report_errors( + let _ = infcx.err_ctxt().check_region_obligations_and_report_errors( defining_use_anchor, &outlives_environment, ); } } // Clean up after ourselves - let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); + let _ = infcx.take_opaque_types(); } fn is_enum_of_nonnullable_ptr<'tcx>( 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 a767338ab85..7af89934d14 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -270,8 +270,8 @@ fn compare_method_predicate_entailment<'tcx>( let unnormalized_impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(unnormalized_impl_sig)); let norm_cause = ObligationCause::misc(impl_m_span, impl_m_hir_id); - let impl_fty = ocx.normalize(&norm_cause, param_env, unnormalized_impl_fty); - debug!("compare_impl_method: impl_fty={:?}", impl_fty); + let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig); + debug!("compare_impl_method: impl_fty={:?}", impl_sig); let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs); let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig); @@ -294,18 +294,17 @@ fn compare_method_predicate_entailment<'tcx>( // type would be more appropriate. In other places we have a `Vec<Span>` // corresponding to their `Vec<Predicate>`, but we don't have that here. // Fixing this would improve the output of test `issue-83765.rs`. - let result = ocx.sup(&cause, param_env, trait_fty, impl_fty); + let result = ocx.sup(&cause, param_env, trait_sig, impl_sig); if let Err(terr) = result { - debug!(?terr, "sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty); + debug!(?impl_sig, ?trait_sig, ?terr, "sub_types failed"); let emitted = report_trait_method_mismatch( &infcx, cause, terr, - (trait_m, trait_fty), - (impl_m, impl_fty), - trait_sig, + (trait_m, trait_sig), + (impl_m, impl_sig), impl_trait_ref, ); return Err(emitted); @@ -425,7 +424,7 @@ fn compare_asyncness<'tcx>( ty::Alias(ty::Opaque, ..) => { // allow both `async fn foo()` and `fn foo() -> impl Future` } - ty::Error(rustc_errors::ErrorGuaranteed { .. }) => { + ty::Error(_) => { // We don't know if it's ok, but at least it's already an error. } _ => { @@ -484,7 +483,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap(); let param_env = tcx.param_env(def_id); - // First, check a few of the same thing as `compare_impl_method`, just so we don't ICE during substitutions later. + // 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, tcx.hir().span_if_local(impl_m.def_id), true)?; compare_generic_param_kinds(tcx, impl_m, trait_m, true)?; check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?; @@ -577,14 +577,11 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( debug!(?trait_sig, ?impl_sig, "equating function signatures"); - let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)); - let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig)); - // Unify the whole function signature. We need to do this to fully infer // the lifetimes of the return type, but do this after unifying just the // return types, since we want to avoid duplicating errors from // `compare_method_predicate_entailment`. - match ocx.eq(&cause, param_env, trait_fty, impl_fty) { + match ocx.eq(&cause, param_env, trait_sig, impl_sig) { Ok(()) => {} Err(terr) => { // This function gets called during `compare_method_predicate_entailment` when normalizing a @@ -595,9 +592,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( infcx, cause, terr, - (trait_m, trait_fty), - (impl_m, impl_fty), - trait_sig, + (trait_m, trait_sig), + (impl_m, impl_sig), impl_trait_ref, ); return Err(emitted); @@ -619,7 +615,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( Some(infcx), infcx.implied_bounds_tys(param_env, impl_m_hir_id, wf_tys), ); - infcx.check_region_obligations_and_report_errors( + infcx.err_ctxt().check_region_obligations_and_report_errors( impl_m.def_id.expect_local(), &outlives_environment, )?; @@ -771,9 +767,8 @@ fn report_trait_method_mismatch<'tcx>( infcx: &InferCtxt<'tcx>, mut cause: ObligationCause<'tcx>, terr: TypeError<'tcx>, - (trait_m, trait_fty): (&ty::AssocItem, Ty<'tcx>), - (impl_m, impl_fty): (&ty::AssocItem, Ty<'tcx>), - trait_sig: ty::FnSig<'tcx>, + (trait_m, trait_sig): (&ty::AssocItem, ty::FnSig<'tcx>), + (impl_m, impl_sig): (&ty::AssocItem, ty::FnSig<'tcx>), impl_trait_ref: ty::TraitRef<'tcx>, ) -> ErrorGuaranteed { let tcx = infcx.tcx; @@ -858,10 +853,7 @@ fn report_trait_method_mismatch<'tcx>( &mut diag, &cause, trait_err_span.map(|sp| (sp, "type in trait".to_owned())), - Some(infer::ValuePairs::Terms(ExpectedFound { - expected: trait_fty.into(), - found: impl_fty.into(), - })), + Some(infer::ValuePairs::Sigs(ExpectedFound { expected: trait_sig, found: impl_sig })), terr, false, false, @@ -1651,8 +1643,9 @@ pub(super) fn compare_impl_const_raw( } let outlives_environment = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?; - + infcx + .err_ctxt() + .check_region_obligations_and_report_errors(impl_const_item_def, &outlives_environment)?; Ok(()) } @@ -1760,7 +1753,7 @@ fn compare_type_predicate_entailment<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let outlives_environment = OutlivesEnvironment::new(param_env); - infcx.check_region_obligations_and_report_errors( + infcx.err_ctxt().check_region_obligations_and_report_errors( impl_ty.def_id.expect_local(), &outlives_environment, )?; @@ -1974,27 +1967,11 @@ pub(super) fn check_type_bounds<'tcx>( let outlives_environment = OutlivesEnvironment::with_bounds(param_env, Some(&infcx), implied_bounds); - infcx.check_region_obligations_and_report_errors( + infcx.err_ctxt().check_region_obligations_and_report_errors( impl_ty.def_id.expect_local(), &outlives_environment, )?; - let constraints = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types(); - for (key, value) in constraints { - infcx - .err_ctxt() - .report_mismatched_types( - &ObligationCause::misc( - value.hidden_type.span, - tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local()), - ), - tcx.mk_opaque(key.def_id.to_def_id(), key.substs), - value.hidden_type.ty, - TypeError::Mismatch, - ) - .emit(); - } - Ok(()) } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0d1aa39c5d9..e9baab59453 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -97,25 +97,28 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( let infcx = &tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new(infcx); - let assumed_wf_types = ocx.assumed_wf_types(param_env, span, body_def_id); - let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env }; if !tcx.features().trivial_bounds { wfcx.check_false_global_bounds() } f(&mut wfcx); + + let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, span, body_def_id); + let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types); + let errors = wfcx.select_all_or_error(); if !errors.is_empty() { infcx.err_ctxt().report_fulfillment_errors(&errors, None); return; } - let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types); let outlives_environment = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds); - let _ = infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment); + let _ = infcx + .err_ctxt() + .check_region_obligations_and_report_errors(body_def_id, &outlives_environment); } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) { @@ -1489,54 +1492,38 @@ fn check_fn_or_method<'tcx>( def_id: LocalDefId, ) { let tcx = wfcx.tcx(); - let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); + let mut sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); // Normalize the input and output types one at a time, using a different // `WellFormedLoc` for each. We cannot call `normalize_associated_types` // on the entire `FnSig`, since this would use the same `WellFormedLoc` // for each type, preventing the HIR wf check from generating // a nice error message. - let ty::FnSig { mut inputs_and_output, c_variadic, unsafety, abi } = sig; - inputs_and_output = tcx.mk_type_list(inputs_and_output.iter().enumerate().map(|(i, ty)| { - wfcx.normalize( - span, - Some(WellFormedLoc::Param { - function: def_id, - // Note that the `param_idx` of the output type is - // one greater than the index of the last input type. - param_idx: i.try_into().unwrap(), - }), - ty, - ) - })); - // Manually call `normalize_associated_types_in` on the other types - // in `FnSig`. This ensures that if the types of these fields - // ever change to include projections, we will start normalizing - // them automatically. - let sig = ty::FnSig { - inputs_and_output, - c_variadic: wfcx.normalize(span, None, c_variadic), - unsafety: wfcx.normalize(span, None, unsafety), - abi: wfcx.normalize(span, None, abi), - }; + let arg_span = + |idx| hir_decl.inputs.get(idx).map_or(hir_decl.output.span(), |arg: &hir::Ty<'_>| arg.span); + + sig.inputs_and_output = + tcx.mk_type_list(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| { + wfcx.normalize( + arg_span(idx), + Some(WellFormedLoc::Param { + function: def_id, + // Note that the `param_idx` of the output type is + // one greater than the index of the last input type. + param_idx: idx.try_into().unwrap(), + }), + ty, + ) + })); - for (i, (&input_ty, ty)) in iter::zip(sig.inputs(), hir_decl.inputs).enumerate() { + for (idx, ty) in sig.inputs_and_output.iter().enumerate() { wfcx.register_wf_obligation( - ty.span, - Some(WellFormedLoc::Param { function: def_id, param_idx: i.try_into().unwrap() }), - input_ty.into(), + arg_span(idx), + Some(WellFormedLoc::Param { function: def_id, param_idx: idx.try_into().unwrap() }), + ty.into(), ); } - wfcx.register_wf_obligation( - hir_decl.output.span(), - Some(WellFormedLoc::Param { - function: def_id, - param_idx: sig.inputs().len().try_into().unwrap(), - }), - sig.output().into(), - ); - check_where_clauses(wfcx, span, def_id); check_return_position_impl_trait_in_trait_bounds( @@ -1912,7 +1899,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { } let pred = obligation.predicate; // Match the existing behavior. - if pred.is_global() && !pred.has_late_bound_regions() { + if pred.is_global() && !pred.has_late_bound_vars() { let pred = self.normalize(span, None, pred); let hir_node = tcx.hir().find(self.body_id); diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index bfedf63da97..2e2c1591e9b 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -325,7 +325,9 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - let _ = infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = infcx + .err_ctxt() + .check_region_obligations_and_report_errors(impl_did, &outlives_env); } } _ => { @@ -565,7 +567,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn // Finally, resolve all regions. let outlives_env = OutlivesEnvironment::new(param_env); - let _ = infcx.check_region_obligations_and_report_errors(impl_did, &outlives_env); + let _ = infcx.err_ctxt().check_region_obligations_and_report_errors(impl_did, &outlives_env); CoerceUnsizedInfo { custom_kind: kind } } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 7afde550b42..b7f259668a1 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -505,9 +505,9 @@ impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> { } } - fn normalize_ty(&self, _span: Span, ty: Ty<'tcx>) -> Ty<'tcx> { - // Types in item signatures are not normalized to avoid undue dependencies. - ty + fn probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> { + // FIXME(#103640): Should we handle the case where `ty` is a projection? + ty.ty_adt_def() } fn set_tainted_by_errors(&self, _: ErrorGuaranteed) { diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 0542e2c8f50..093e9560ccd 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -28,7 +28,7 @@ fn associated_type_bounds<'tcx>( let icx = ItemCtxt::new(tcx, assoc_item_def_id); let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds); // Associated types are implicitly sized unless a `?Sized` bound is found - <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); + <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, item_ty, ast_bounds, None, span); let trait_def_id = tcx.parent(assoc_item_def_id); let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local()); @@ -44,9 +44,7 @@ fn associated_type_bounds<'tcx>( } }); - let all_bounds = tcx - .arena - .alloc_from_iter(bounds.predicates(tcx, item_ty).into_iter().chain(bounds_from_parent)); + let all_bounds = tcx.arena.alloc_from_iter(bounds.predicates().chain(bounds_from_parent)); debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds); all_bounds } @@ -74,10 +72,10 @@ fn opaque_type_bounds<'tcx>( let icx = ItemCtxt::new(tcx, opaque_def_id); let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds); // Opaque types are implicitly sized unless a `?Sized` bound is found - <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); + <dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, item_ty, ast_bounds, None, span); debug!(?bounds); - tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty)) + tcx.arena.alloc_from_iter(bounds.predicates()) }) } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 8412b7418b3..18fc43ce15c 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -165,12 +165,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP <dyn AstConv<'_>>::add_implicitly_sized( &icx, &mut bounds, + param_ty, &[], Some((param.def_id, ast_generics.predicates)), param.span, ); trace!(?bounds); - predicates.extend(bounds.predicates(tcx, param_ty)); + predicates.extend(bounds.predicates()); trace!(?predicates); } GenericParamKind::Const { .. } => { @@ -217,7 +218,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP &mut bounds, bound_vars, ); - predicates.extend(bounds.predicates(tcx, ty)); + predicates.extend(bounds.predicates()); } hir::WherePredicate::RegionPredicate(region_pred) => { @@ -536,7 +537,7 @@ pub(super) fn super_predicates_that_define_assoc_type( <dyn AstConv<'_>>::compute_bounds(&icx, self_param_ty, bounds) }; - let superbounds1 = superbounds1.predicates(tcx, self_param_ty); + let superbounds1 = superbounds1.predicates(); // Convert any explicit superbounds in the where-clause, // e.g., `trait Foo where Self: Bar`. @@ -745,5 +746,5 @@ fn predicates_from_bound<'tcx>( ) -> Vec<(ty::Predicate<'tcx>, Span)> { let mut bounds = Bounds::default(); astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars); - bounds.predicates(astconv.tcx(), param_ty).collect() + bounds.predicates().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 1aae9e0bd20..8b9034d9620 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 @@ -181,7 +181,8 @@ fn get_impl_substs( let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_hir_id, assumed_wf_types); let outlives_env = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds); - let _ = infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env); + let _ = + infcx.err_ctxt().check_region_obligations_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 }); |
