From dc0db358abe19481e475e10c32149b53370f1a1c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:57:31 +0200 Subject: Merging upstream version 1.72.1+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_infer/messages.ftl | 3 - compiler/rustc_infer/src/errors/mod.rs | 24 --- compiler/rustc_infer/src/infer/at.rs | 5 +- .../src/infer/canonical/canonicalizer.rs | 13 +- compiler/rustc_infer/src/infer/canonical/mod.rs | 8 +- .../src/infer/canonical/query_response.rs | 33 ++-- compiler/rustc_infer/src/infer/combine.rs | 63 ++++--- compiler/rustc_infer/src/infer/equate.rs | 2 +- .../rustc_infer/src/infer/error_reporting/mod.rs | 49 ++++-- .../src/infer/error_reporting/need_type_info.rs | 6 +- .../nice_region_error/placeholder_error.rs | 10 +- .../nice_region_error/static_impl_trait.rs | 2 +- .../nice_region_error/trait_impl_difference.rs | 4 +- .../rustc_infer/src/infer/error_reporting/note.rs | 4 +- .../src/infer/error_reporting/note_and_explain.rs | 54 +++--- .../src/infer/error_reporting/suggest.rs | 27 +-- compiler/rustc_infer/src/infer/freshen.rs | 8 +- compiler/rustc_infer/src/infer/generalize.rs | 10 +- .../rustc_infer/src/infer/higher_ranked/mod.rs | 33 ++-- compiler/rustc_infer/src/infer/lattice.rs | 2 +- .../src/infer/lexical_region_resolve/mod.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 190 ++++++++++----------- compiler/rustc_infer/src/infer/nll_relate/mod.rs | 6 +- compiler/rustc_infer/src/infer/opaque_types.rs | 138 ++++++++------- .../rustc_infer/src/infer/opaque_types/table.rs | 4 +- compiler/rustc_infer/src/infer/outlives/mod.rs | 29 ++-- .../rustc_infer/src/infer/outlives/obligations.rs | 5 +- compiler/rustc_infer/src/infer/outlives/verify.rs | 12 +- compiler/rustc_infer/src/infer/projection.rs | 36 ++-- .../src/infer/region_constraints/leak_check.rs | 144 ++++++++-------- .../src/infer/region_constraints/mod.rs | 19 +-- compiler/rustc_infer/src/infer/sub.rs | 4 +- compiler/rustc_infer/src/infer/type_variable.rs | 3 +- compiler/rustc_infer/src/infer/undo_log.rs | 15 +- .../rustc_infer/src/traits/error_reporting/mod.rs | 8 +- compiler/rustc_infer/src/traits/mod.rs | 11 +- compiler/rustc_infer/src/traits/util.rs | 128 +++++++++----- 37 files changed, 547 insertions(+), 567 deletions(-) (limited to 'compiler/rustc_infer') diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl index f44c4a7c1..4d0e77063 100644 --- a/compiler/rustc_infer/messages.ftl +++ b/compiler/rustc_infer/messages.ftl @@ -278,9 +278,6 @@ infer_ril_introduced_by = requirement introduced by this return type infer_ril_introduced_here = `'static` requirement introduced here infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type -infer_sarwa_option = you can convert from `&Option` to `Option<&T>` using `.as_ref()` -infer_sarwa_result = you can convert from `&Result` to `Result<&T, &E>` using `.as_ref()` - infer_sbfrit_box_return_expr = if you change the return type to expect trait objects, box the returned expressions infer_sbfrit_change_return_type = you could change the return type to be a boxed trait object diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index b1e819e83..7e1fa08f2 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -1246,30 +1246,6 @@ pub struct FnConsiderCasting { pub casting: String, } -#[derive(Subdiagnostic)] -pub enum SuggestAsRefWhereAppropriate<'a> { - #[suggestion( - infer_sarwa_option, - code = "{snippet}.as_ref()", - applicability = "machine-applicable" - )] - Option { - #[primary_span] - span: Span, - snippet: &'a str, - }, - #[suggestion( - infer_sarwa_result, - code = "{snippet}.as_ref()", - applicability = "machine-applicable" - )] - Result { - #[primary_span] - span: Span, - snippet: &'a str, - }, -} - #[derive(Subdiagnostic)] pub enum SuggestAccessingField<'a> { #[suggestion( diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 0c8854e96..433735e82 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -40,6 +40,7 @@ pub enum DefineOpaqueTypes { No, } +#[derive(Clone, Copy)] pub struct At<'a, 'tcx> { pub infcx: &'a InferCtxt<'tcx>, pub cause: &'a ObligationCause<'tcx>, @@ -70,8 +71,8 @@ impl<'tcx> InferCtxt<'tcx> { tcx: self.tcx, defining_use_anchor: self.defining_use_anchor, considering_regions: self.considering_regions, + skip_leak_check: self.skip_leak_check, inner: self.inner.clone(), - skip_leak_check: self.skip_leak_check.clone(), lexical_region_resolutions: self.lexical_region_resolutions.clone(), selection_cache: self.selection_cache.clone(), evaluation_cache: self.evaluation_cache.clone(), @@ -79,9 +80,9 @@ impl<'tcx> InferCtxt<'tcx> { reported_closure_mismatch: self.reported_closure_mismatch.clone(), tainted_by_errors: self.tainted_by_errors.clone(), err_count_on_creation: self.err_count_on_creation, - in_snapshot: self.in_snapshot.clone(), universe: self.universe.clone(), intercrate: self.intercrate, + next_trait_solver: self.next_trait_solver, } } } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 427d05c8b..e57532e2d 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -382,7 +382,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { // any equated inference vars correctly! let root_vid = self.infcx.root_var(vid); if root_vid != vid { - t = self.infcx.tcx.mk_ty_var(root_vid); + t = Ty::new_var(self.infcx.tcx, root_vid); vid = root_vid; } @@ -497,7 +497,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { // any equated inference vars correctly! let root_vid = self.infcx.root_const_var(vid); if root_vid != vid { - ct = self.infcx.tcx.mk_const(ty::InferConst::Var(root_vid), ct.ty()); + ct = ty::Const::new_var(self.infcx.tcx, root_vid, ct.ty()); vid = root_vid; } @@ -771,7 +771,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { ) -> ty::Region<'tcx> { let var = self.canonical_var(info, r.into()); let br = ty::BoundRegion { var, kind: ty::BrAnon(None) }; - self.interner().mk_re_late_bound(self.binder_index, br) + ty::Region::new_late_bound(self.interner(), self.binder_index, br) } /// Given a type variable `ty_var` of the given kind, first check @@ -785,7 +785,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { self.fold_ty(bound_to) } else { let var = self.canonical_var(info, ty_var.into()); - self.interner().mk_bound(self.binder_index, var.into()) + Ty::new_bound(self.tcx, self.binder_index, var.into()) } } @@ -804,10 +804,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { self.fold_const(bound_to) } else { let var = self.canonical_var(info, const_var.into()); - self.interner().mk_const( - ty::ConstKind::Bound(self.binder_index, var), - self.fold_ty(const_var.ty()), - ) + ty::Const::new_bound(self.tcx, self.binder_index, var, self.fold_ty(const_var.ty())) } } } diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index 2abdd5b0a..f765c41a3 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -26,7 +26,7 @@ use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVari use rustc_index::IndexVec; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::GenericArg; -use rustc_middle::ty::{self, List, TyCtxt}; +use rustc_middle::ty::{self, List, Ty, TyCtxt}; use rustc_span::source_map::Span; pub use rustc_middle::infer::canonical::*; @@ -128,7 +128,7 @@ impl<'tcx> InferCtxt<'tcx> { CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, bound }) => { let universe_mapped = universe_map(universe); let placeholder_mapped = ty::PlaceholderType { universe: universe_mapped, bound }; - self.tcx.mk_placeholder(placeholder_mapped).into() + Ty::new_placeholder(self.tcx, placeholder_mapped).into() } CanonicalVarKind::Region(ui) => self @@ -141,7 +141,7 @@ impl<'tcx> InferCtxt<'tcx> { CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, bound }) => { let universe_mapped = universe_map(universe); let placeholder_mapped = ty::PlaceholderRegion { universe: universe_mapped, bound }; - self.tcx.mk_re_placeholder(placeholder_mapped).into() + ty::Region::new_placeholder(self.tcx, placeholder_mapped).into() } CanonicalVarKind::Const(ui, ty) => self @@ -155,7 +155,7 @@ impl<'tcx> InferCtxt<'tcx> { CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }, ty) => { let universe_mapped = universe_map(universe); let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, bound }; - self.tcx.mk_const(placeholder_mapped, ty).into() + ty::Const::new_placeholder(self.tcx, placeholder_mapped, ty).into() } } } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 88256c819..9c3ab04de 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -520,7 +520,7 @@ impl<'tcx> InferCtxt<'tcx> { self.at(cause, param_env) .eq( DefineOpaqueTypes::Yes, - self.tcx.mk_opaque(a.def_id.to_def_id(), a.substs), + Ty::new_opaque(self.tcx, a.def_id.to_def_id(), a.substs), b, )? .obligations, @@ -584,12 +584,12 @@ impl<'tcx> InferCtxt<'tcx> { let ty::OutlivesPredicate(k1, r2) = predicate; let atom = match k1.unpack() { - GenericArgKind::Lifetime(r1) => { - ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate(r1, r2))) - } - GenericArgKind::Type(t1) => { - ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(t1, r2))) - } + GenericArgKind::Lifetime(r1) => ty::PredicateKind::Clause( + ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)), + ), + GenericArgKind::Type(t1) => ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives( + ty::OutlivesPredicate(t1, r2), + )), GenericArgKind::Const(..) => { // Consts cannot outlive one another, so we don't expect to // encounter this branch. @@ -668,14 +668,15 @@ pub fn make_query_region_constraints<'tcx>( let constraint = match *k { // Swap regions because we are going from sub (<=) to outlives // (>=). - Constraint::VarSubVar(v1, v2) => { - ty::OutlivesPredicate(tcx.mk_re_var(v2).into(), tcx.mk_re_var(v1)) - } + Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate( + ty::Region::new_var(tcx, v2).into(), + ty::Region::new_var(tcx, v1), + ), Constraint::VarSubReg(v1, r2) => { - ty::OutlivesPredicate(r2.into(), tcx.mk_re_var(v1)) + ty::OutlivesPredicate(r2.into(), ty::Region::new_var(tcx, v1)) } Constraint::RegSubVar(r1, v2) => { - ty::OutlivesPredicate(tcx.mk_re_var(v2).into(), r1) + ty::OutlivesPredicate(ty::Region::new_var(tcx, v2).into(), r1) } Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r2.into(), r1), }; @@ -719,7 +720,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { } fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> { - self.infcx.tcx.mk_re_placeholder(placeholder) + ty::Region::new_placeholder(self.infcx.tcx, placeholder) } fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { @@ -738,10 +739,8 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for QueryTypeRelatingDelegate<'_, 'tcx> { self.obligations.push(Obligation { cause: self.cause.clone(), param_env: self.param_env, - predicate: ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives( - ty::OutlivesPredicate(sup, sub), - ))) - .to_predicate(self.infcx.tcx), + predicate: ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(sup, sub)) + .to_predicate(self.infcx.tcx), recursion_depth: 0, }); } diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index b6b935de6..a9cdb8c51 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -34,7 +34,7 @@ use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{RelateResult, TypeRelation}; -use rustc_middle::ty::{self, AliasKind, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{IntType, UintType}; use rustc_span::DUMMY_SP; @@ -103,17 +103,17 @@ impl<'tcx> InferCtxt<'tcx> { // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm. ( - ty::Alias(AliasKind::Projection, _), + ty::Alias(..), ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), ) | ( ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), - ty::Alias(AliasKind::Projection, _), - ) if self.tcx.trait_solver_next() => { + ty::Alias(..), + ) if self.next_trait_solver() => { bug!() } - (_, ty::Alias(..)) | (ty::Alias(..), _) if self.tcx.trait_solver_next() => { + (_, ty::Alias(..)) | (ty::Alias(..), _) if self.next_trait_solver() => { relation.register_type_relate_obligation(a, b); Ok(a) } @@ -124,13 +124,10 @@ impl<'tcx> InferCtxt<'tcx> { } // During coherence, opaque types should be treated as *possibly* - // equal to each other, even if their generic params differ, as - // they could resolve to the same hidden type, even for different - // generic params. - ( - &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }), - &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }), - ) if self.intercrate && a_def_id == b_def_id => { + // equal to any other type (except for possibly itself). This is an + // extremely heavy hammer, but can be relaxed in a fowards-compatible + // way later. + (&ty::Alias(ty::Opaque, _), _) | (_, &ty::Alias(ty::Opaque, _)) if self.intercrate => { relation.register_predicates([ty::Binder::dummy(ty::PredicateKind::Ambiguous)]); Ok(a) } @@ -192,11 +189,11 @@ impl<'tcx> InferCtxt<'tcx> { // HACK: equating both sides with `[const error]` eagerly prevents us // from leaving unconstrained inference vars during things like impl // matching in the solver. - let a_error = self.tcx.const_error(a.ty(), guar); + let a_error = ty::Const::new_error(self.tcx, guar, a.ty()); if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() { return self.unify_const_variable(vid, a_error, relation.param_env()); } - let b_error = self.tcx.const_error(b.ty(), guar); + let b_error = ty::Const::new_error(self.tcx, guar, b.ty()); if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() { return self.unify_const_variable(vid, b_error, relation.param_env()); } @@ -227,9 +224,20 @@ impl<'tcx> InferCtxt<'tcx> { return self.unify_const_variable(vid, a, relation.param_env()); } (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) - if self.tcx.lazy_normalization() => + if self.tcx.features().generic_const_exprs || self.next_trait_solver() => { - relation.register_const_equate_obligation(a, b); + let (a, b) = if relation.a_is_expected() { (a, b) } else { (b, a) }; + + relation.register_predicates([ty::Binder::dummy(if self.next_trait_solver() { + ty::PredicateKind::AliasRelate( + a.into(), + b.into(), + ty::AliasRelationDirection::Equate, + ) + } else { + ty::PredicateKind::ConstEquate(a, b) + })]); + return Ok(b); } _ => {} @@ -314,8 +322,8 @@ impl<'tcx> InferCtxt<'tcx> { .unify_var_value(vid, Some(val)) .map_err(|e| int_unification_error(vid_is_expected, e))?; match val { - IntType(v) => Ok(self.tcx.mk_mach_int(v)), - UintType(v) => Ok(self.tcx.mk_mach_uint(v)), + IntType(v) => Ok(Ty::new_int(self.tcx, v)), + UintType(v) => Ok(Ty::new_uint(self.tcx, v)), } } @@ -330,7 +338,7 @@ impl<'tcx> InferCtxt<'tcx> { .float_unification_table() .unify_var_value(vid, Some(ty::FloatVarValue(val))) .map_err(|e| float_unification_error(vid_is_expected, e))?; - Ok(self.tcx.mk_mach_float(val)) + Ok(Ty::new_float(self.tcx, val)) } } @@ -406,7 +414,9 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { self.tcx(), self.trace.cause.clone(), self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(b_ty.into())), + ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed( + b_ty.into(), + ))), )); } @@ -453,19 +463,6 @@ pub trait ObligationEmittingRelation<'tcx>: TypeRelation<'tcx> { /// be used if control over the obligation causes is required. fn register_predicates(&mut self, obligations: impl IntoIterator>); - /// Register an obligation that both constants must be equal to each other. - /// - /// If they aren't equal then the relation doesn't hold. - fn register_const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) { - let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) }; - - self.register_predicates([ty::Binder::dummy(if self.tcx().trait_solver_next() { - ty::PredicateKind::AliasRelate(a.into(), b.into(), ty::AliasRelationDirection::Equate) - } else { - ty::PredicateKind::ConstEquate(a, b) - })]); - } - /// Register an obligation that both types must be related to each other according to /// the [`ty::AliasRelationDirection`] given by [`ObligationEmittingRelation::alias_relate_direction`] fn register_type_relate_obligation(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { diff --git a/compiler/rustc_infer/src/infer/equate.rs b/compiler/rustc_infer/src/infer/equate.rs index 42dfe4f6b..495c250a7 100644 --- a/compiler/rustc_infer/src/infer/equate.rs +++ b/compiler/rustc_infer/src/infer/equate.rs @@ -105,7 +105,7 @@ impl<'tcx> TypeRelation<'tcx> for Equate<'_, '_, 'tcx> { | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) if self.fields.define_opaque_types == DefineOpaqueTypes::Yes && def_id.is_local() - && !self.tcx().trait_solver_next() => + && !self.fields.infcx.next_trait_solver() => { self.fields.obligations.extend( infcx diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 35c05e80b..b826ced04 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -76,6 +76,7 @@ use rustc_middle::ty::{ }; use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span}; use rustc_target::spec::abi; +use std::borrow::Cow; use std::ops::{ControlFlow, Deref}; use std::path::PathBuf; use std::{cmp, fmt, iter}; @@ -314,7 +315,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = tcx.sess.create_err(errors::OpaqueCapturesLifetime { span, - opaque_ty: tcx.mk_opaque(opaque_ty_key.def_id.to_def_id(), opaque_ty_key.substs), + opaque_ty: Ty::new_opaque(tcx, opaque_ty_key.def_id.to_def_id(), opaque_ty_key.substs), opaque_ty_span: tcx.def_span(opaque_ty_key.def_id), }); @@ -407,7 +408,7 @@ impl<'tcx> InferCtxt<'tcx> { predicate .kind() .map_bound(|kind| match kind { - ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate)) + ty::ClauseKind::Projection(projection_predicate) if projection_predicate.projection_ty.def_id == item_def_id => { projection_predicate.term.ty() @@ -846,7 +847,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ) { err.subdiagnostic(subdiag); } - if let Some(ret_sp) = opt_suggest_box_span { + // don't suggest wrapping either blocks in `if .. {} else {}` + let is_empty_arm = |id| { + let hir::Node::Block(blk) = self.tcx.hir().get(id) + else { + return false; + }; + if blk.expr.is_some() || !blk.stmts.is_empty() { + return false; + } + let Some((_, hir::Node::Expr(expr))) = self.tcx.hir().parent_iter(id).nth(1) + else { + return false; + }; + matches!(expr.kind, hir::ExprKind::If(..)) + }; + if let Some(ret_sp) = opt_suggest_box_span + && !is_empty_arm(then_id) + && !is_empty_arm(else_id) + { self.suggest_boxing_for_return_impl_trait( err, ret_sp, @@ -1470,7 +1489,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &self, diag: &mut Diagnostic, cause: &ObligationCause<'tcx>, - secondary_span: Option<(Span, String)>, + secondary_span: Option<(Span, Cow<'static, str>)>, mut values: Option>, terr: TypeError<'tcx>, swap_secondary_and_primary: bool, @@ -1629,7 +1648,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } }; - let mut label_or_note = |span: Span, msg: &str| { + let mut label_or_note = |span: Span, msg: Cow<'static, str>| { if (prefer_label && is_simple_error) || &[span] == diag.span.primary_spans() { diag.span_label(span, msg); } else { @@ -1643,15 +1662,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .. })) = values { - format!("expected this to be `{}`", expected) + Cow::from(format!("expected this to be `{}`", expected)) } else { - terr.to_string(self.tcx).to_string() + terr.to_string(self.tcx) }; - label_or_note(sp, &terr); - label_or_note(span, &msg); + label_or_note(sp, terr); + label_or_note(span, msg); } else { - label_or_note(span, &terr.to_string(self.tcx)); - label_or_note(sp, &msg); + label_or_note(span, terr.to_string(self.tcx)); + label_or_note(sp, msg); } } else { if let Some(values) = values @@ -1663,12 +1682,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let expected = with_forced_trimmed_paths!(e.sort_string(self.tcx)); let found = with_forced_trimmed_paths!(f.sort_string(self.tcx)); if expected == found { - label_or_note(span, &terr.to_string(self.tcx)); + label_or_note(span, terr.to_string(self.tcx)); } else { - label_or_note(span, &format!("expected {expected}, found {found}")); + label_or_note(span, Cow::from(format!("expected {expected}, found {found}"))); } } else { - label_or_note(span, &terr.to_string(self.tcx)); + label_or_note(span, terr.to_string(self.tcx)); } } @@ -1896,7 +1915,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { if should_suggest_fixes { self.suggest_tuple_pattern(cause, &exp_found, diag); - self.suggest_as_ref_where_appropriate(span, &exp_found, diag); self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag); self.suggest_await_on_expect_found(cause, span, &exp_found, diag); self.suggest_function_pointers(cause, span, &exp_found, diag); @@ -2357,6 +2375,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ty::AliasKind::Projection | ty::AliasKind::Inherent => { format!("the associated type `{}`", p) } + ty::AliasKind::Weak => format!("the type alias `{}`", p), ty::AliasKind::Opaque => format!("the opaque type `{}`", p), }, }; diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index f3b2ec4c5..bb75ecc6a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -265,9 +265,9 @@ impl<'tcx> InferCtxt<'tcx> { kind: UnderspecifiedArgKind::Type { prefix: "type parameter".into(), }, - parent: def_id.and_then(|def_id| { - InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id) - }), + parent: InferenceDiagnosticsParentData::for_def_id( + self.tcx, def_id, + ), }; } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index c9c1f0aea..0b3bc1ce6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -79,7 +79,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { sup_placeholder @ Region(Interned(RePlaceholder(_), _)), _, )) => self.try_report_trait_placeholder_mismatch( - Some(self.tcx().mk_re_var(*vid)), + Some(ty::Region::new_var(self.tcx(), *vid)), cause, Some(*sub_placeholder), Some(*sup_placeholder), @@ -95,7 +95,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { _, _, )) => self.try_report_trait_placeholder_mismatch( - Some(self.tcx().mk_re_var(*vid)), + Some(ty::Region::new_var(self.tcx(), *vid)), cause, Some(*sub_placeholder), None, @@ -111,7 +111,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { sup_placeholder @ Region(Interned(RePlaceholder(_), _)), _, )) => self.try_report_trait_placeholder_mismatch( - Some(self.tcx().mk_re_var(*vid)), + Some(ty::Region::new_var(self.tcx(), *vid)), cause, None, Some(*sup_placeholder), @@ -127,7 +127,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { sup_placeholder @ Region(Interned(RePlaceholder(_), _)), _, )) => self.try_report_trait_placeholder_mismatch( - Some(self.tcx().mk_re_var(*vid)), + Some(ty::Region::new_var(self.tcx(), *vid)), cause, None, Some(*sup_placeholder), @@ -141,7 +141,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { SubregionOrigin::Subtype(box TypeTrace { cause, values }), sup_placeholder @ Region(Interned(RePlaceholder(_), _)), )) => self.try_report_trait_placeholder_mismatch( - Some(self.tcx().mk_re_var(*vid)), + Some(ty::Region::new_var(self.tcx(), *vid)), cause, None, Some(*sup_placeholder), diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index aad988582..a9b485a6f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -288,7 +288,7 @@ pub fn suggest_new_region_bound( // Get the identity type for this RPIT let did = item_id.owner_id.to_def_id(); - let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did)); + let ty = Ty::new_opaque(tcx, did, ty::InternalSubsts::identity_for_item(tcx, did)); if let Some(span) = opaque.bounds.iter().find_map(|arg| match arg { GenericBound::Outlives(Lifetime { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index ce70bcc5c..12d38ced0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -41,8 +41,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // all of the region highlighting machinery only deals with those. let guar = self.emit_err( var_origin.span(), - self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(expected)), - self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(found)), + Ty::new_fn_ptr(self.cx.tcx,ty::Binder::dummy(expected)), + Ty::new_fn_ptr(self.cx.tcx,ty::Binder::dummy(found)), *trait_item_def_id, ); return Some(guar); diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 07a9eff2d..e55e9e75f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -11,7 +11,7 @@ use rustc_errors::{ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::traits::ObligationCauseCode; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::{self, IsSuggestable, Region}; +use rustc_middle::ty::{self, IsSuggestable, Region, Ty}; use rustc_span::symbol::kw; use super::ObligationCauseAsDiagArg; @@ -304,7 +304,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let trait_substs = trait_ref .subst_identity() // Replace the explicit self type with `Self` for better suggestion rendering - .with_self_ty(self.tcx, self.tcx.mk_ty_param(0, kw::SelfUpper)) + .with_self_ty(self.tcx, Ty::new_param(self.tcx, 0, kw::SelfUpper)) .substs; let trait_item_substs = ty::InternalSubsts::identity_for_item(self.tcx, impl_item_def_id) .rebase_onto(self.tcx, impl_def_id, trait_substs); diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs index 421eb807a..63613b590 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs @@ -139,7 +139,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { tcx, generics, diag, - &format!("{}", proj.self_ty()), + &proj.self_ty().to_string(), &path, None, matching_span, @@ -153,7 +153,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { tcx, generics, diag, - &format!("{}", proj.self_ty()), + &proj.self_ty().to_string(), &path, None, matching_span, @@ -234,13 +234,13 @@ impl Trait for X { ); } (_, ty::Alias(ty::Projection | ty::Inherent, proj_ty)) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => { - let msg = format!( + let msg = || format!( "consider constraining the associated type `{}` to `{}`", values.found, values.expected, ); if !(self.suggest_constraining_opaque_associated_type( diag, - &msg, + msg, proj_ty, values.expected, ) || self.suggest_constraint( @@ -250,17 +250,18 @@ impl Trait for X { proj_ty, values.expected, )) { - diag.help(msg); + diag.help(msg()); diag.note( "for more information, visit \ https://doc.rust-lang.org/book/ch19-03-advanced-traits.html", ); } } - (ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::AssocFn | DefKind::AssocConst) => { + (ty::Alias(ty::Opaque, alias), _) | (_, ty::Alias(ty::Opaque, alias)) if alias.def_id.is_local() && matches!(tcx.def_kind(body_owner_def_id), DefKind::Fn | DefKind::Static(_) | DefKind::Const | DefKind::AssocFn | DefKind::AssocConst) => { if tcx.is_type_alias_impl_trait(alias.def_id) { if !tcx.opaque_types_defined_by(body_owner_def_id.expect_local()).contains(&alias.def_id.expect_local()) { - diag.span_note(tcx.def_span(body_owner_def_id), "\ + let sp = tcx.def_ident_span(body_owner_def_id).unwrap_or_else(|| tcx.def_span(body_owner_def_id)); + diag.span_note(sp, "\ this item must have the opaque type in its signature \ in order to be able to register hidden types"); } @@ -308,7 +309,7 @@ impl Trait for X { fn suggest_constraint( &self, diag: &mut Diagnostic, - msg: &str, + msg: impl Fn() -> String, body_owner_def_id: DefId, proj_ty: &ty::AliasTy<'tcx>, ty: Ty<'tcx>, @@ -340,7 +341,7 @@ impl Trait for X { assoc, assoc_substs, ty, - msg, + &msg, false, ) { return true; @@ -374,10 +375,18 @@ impl Trait for X { ) { let tcx = self.tcx; - let msg = format!( - "consider constraining the associated type `{}` to `{}`", - values.expected, values.found - ); + // Don't suggest constraining a projection to something containing itself + if self.tcx.erase_regions(values.found).contains(self.tcx.erase_regions(values.expected)) { + return; + } + + let msg = || { + format!( + "consider constraining the associated type `{}` to `{}`", + values.expected, values.found + ) + }; + let body_owner = tcx.hir().get_if_local(body_owner_def_id); let current_method_ident = body_owner.and_then(|n| n.ident()).map(|i| i.name); @@ -428,10 +437,11 @@ impl Trait for X { if callable_scope { diag.help(format!( "{} or calling a method that returns `{}`", - msg, values.expected + msg(), + values.expected )); } else { - diag.help(msg); + diag.help(msg()); } diag.note( "for more information, visit \ @@ -463,7 +473,7 @@ fn foo(&self) -> Self::T { String::new() } fn suggest_constraining_opaque_associated_type( &self, diag: &mut Diagnostic, - msg: &str, + msg: impl Fn() -> String, proj_ty: &ty::AliasTy<'tcx>, ty: Ty<'tcx>, ) -> bool { @@ -564,7 +574,9 @@ fn foo(&self) -> Self::T { String::new() } let Some(hir_id) = body_owner_def_id.as_local() else { return false; }; - let hir_id = tcx.hir().local_def_id_to_hir_id(hir_id); + let Some(hir_id) = tcx.opt_local_def_id_to_hir_id(hir_id) else { + return false; + }; // When `body_owner` is an `impl` or `trait` item, look in its associated types for // `expected` and point at it. let parent_id = tcx.hir().get_parent_item(hir_id); @@ -583,7 +595,7 @@ fn foo(&self) -> Self::T { String::new() } // FIXME: account for returning some type in a trait fn impl that has // an assoc type as a return type (#72076). if let hir::Defaultness::Default { has_value: true } = - tcx.impl_defaultness(item.id.owner_id) + tcx.defaultness(item.id.owner_id) { let assoc_ty = tcx.type_of(item.id.owner_id).subst_identity(); if self.infcx.can_eq(param_env, assoc_ty, found) { @@ -635,7 +647,7 @@ fn foo(&self) -> Self::T { String::new() } assoc: ty::AssocItem, assoc_substs: &[ty::GenericArg<'tcx>], ty: Ty<'tcx>, - msg: &str, + msg: impl Fn() -> String, is_bound_surely_present: bool, ) -> bool { // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting. @@ -678,7 +690,7 @@ fn foo(&self) -> Self::T { String::new() } assoc: ty::AssocItem, assoc_substs: &[ty::GenericArg<'tcx>], ty: Ty<'tcx>, - msg: &str, + msg: impl Fn() -> String, ) -> bool { let tcx = self.tcx; @@ -693,7 +705,7 @@ fn foo(&self) -> Self::T { String::new() } let item_args = self.format_generic_args(assoc_substs); (span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident(tcx), item_args, ty)) }; - diag.span_suggestion_verbose(span, msg, sugg, MaybeIncorrect); + diag.span_suggestion_verbose(span, msg(), sugg, MaybeIncorrect); return true; } false diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index d885d0407..1422bdc9e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -13,9 +13,9 @@ use rustc_span::{sym, BytePos, Span}; use crate::errors::{ ConsiderAddingAwait, FnConsiderCasting, FnItemsAreDistinct, FnUniqTypes, - FunctionPointerSuggestion, SuggestAccessingField, SuggestAsRefWhereAppropriate, - SuggestBoxingForReturnImplTrait, SuggestRemoveSemiOrReturnBinding, SuggestTuplePatternMany, - SuggestTuplePatternOne, TypeErrorAdditionalDiags, + FunctionPointerSuggestion, SuggestAccessingField, SuggestBoxingForReturnImplTrait, + SuggestRemoveSemiOrReturnBinding, SuggestTuplePatternMany, SuggestTuplePatternOne, + TypeErrorAdditionalDiags, }; use super::TypeErrCtxt; @@ -289,27 +289,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } - /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate, - /// suggests it. - pub(super) fn suggest_as_ref_where_appropriate( - &self, - span: Span, - exp_found: &ty::error::ExpectedFound>, - diag: &mut Diagnostic, - ) { - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) - && let Some(msg) = self.should_suggest_as_ref_kind(exp_found.expected, exp_found.found) - { - // HACK: fix issue# 100605, suggesting convert from &Option to Option<&T>, remove the extra `&` - let snippet = snippet.trim_start_matches('&'); - let subdiag = match msg { - SuggestAsRefKind::Option => SuggestAsRefWhereAppropriate::Option { span, snippet }, - SuggestAsRefKind::Result => SuggestAsRefWhereAppropriate::Result { span, snippet }, - }; - diag.subdiagnostic(subdiag); - } - } - pub(super) fn suggest_function_pointers( &self, cause: &ObligationCause<'tcx>, diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 0219167f6..05769b790 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -95,7 +95,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { Entry::Vacant(entry) => { let index = self.const_freshen_count; self.const_freshen_count += 1; - let ct = self.infcx.tcx.mk_const(freshener(index), ty); + let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index), ty); entry.insert(ct); ct } @@ -188,7 +188,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { match v { ty::TyVar(v) => { let opt_ty = self.infcx.inner.borrow_mut().type_variables().probe(v).known(); - Some(self.freshen_ty(opt_ty, ty::TyVar(v), |n| self.infcx.tcx.mk_fresh_ty(n))) + Some(self.freshen_ty(opt_ty, ty::TyVar(v), |n| Ty::new_fresh(self.infcx.tcx, n))) } ty::IntVar(v) => Some( @@ -200,7 +200,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { .probe_value(v) .map(|v| v.to_type(self.infcx.tcx)), ty::IntVar(v), - |n| self.infcx.tcx.mk_fresh_int_ty(n), + |n| Ty::new_fresh_int(self.infcx.tcx, n), ), ), @@ -213,7 +213,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { .probe_value(v) .map(|v| v.to_type(self.infcx.tcx)), ty::FloatVar(v), - |n| self.infcx.tcx.mk_fresh_float_ty(n), + |n| Ty::new_fresh_float(self.infcx.tcx, n), ), ), diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/generalize.rs index d4a1dacde..780250167 100644 --- a/compiler/rustc_infer/src/infer/generalize.rs +++ b/compiler/rustc_infer/src/infer/generalize.rs @@ -277,7 +277,7 @@ where let origin = *inner.type_variables().var_origin(vid); let new_var_id = inner.type_variables().new_var(self.for_universe, origin); - let u = self.tcx().mk_ty_var(new_var_id); + let u = Ty::new_var(self.tcx(), new_var_id); // Record that we replaced `vid` with `new_var_id` as part of a generalization // operation. This is needed to detect cyclic types. To see why, see the @@ -398,7 +398,7 @@ where origin: var_value.origin, val: ConstVariableValue::Unknown { universe: self.for_universe }, }); - Ok(self.tcx().mk_const(new_var_id, c.ty())) + Ok(ty::Const::new_var(self.tcx(), new_var_id, c.ty())) } } } @@ -412,7 +412,11 @@ where substs, substs, )?; - Ok(self.tcx().mk_const(ty::UnevaluatedConst { def, substs }, c.ty())) + Ok(ty::Const::new_unevaluated( + self.tcx(), + ty::UnevaluatedConst { def, substs }, + c.ty(), + )) } ty::ConstKind::Placeholder(placeholder) => { if self.for_universe.can_name(placeholder.universe) { diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs index c304cd25c..510b1797d 100644 --- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs +++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs @@ -6,7 +6,7 @@ use super::{HigherRankedType, InferCtxt}; use crate::infer::CombinedSnapshot; use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; -use rustc_middle::ty::{self, Binder, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, Binder, Ty, TyCtxt, TypeFoldable}; impl<'a, 'tcx> CombineFields<'a, 'tcx> { /// Checks whether `for<..> sub <: for<..> sup` holds. @@ -82,17 +82,20 @@ impl<'tcx> InferCtxt<'tcx> { let delegate = FnMutDelegate { regions: &mut |br: ty::BoundRegion| { - self.tcx - .mk_re_placeholder(ty::PlaceholderRegion { universe: next_universe, bound: br }) + ty::Region::new_placeholder( + self.tcx, + ty::PlaceholderRegion { universe: next_universe, bound: br }, + ) }, types: &mut |bound_ty: ty::BoundTy| { - self.tcx.mk_placeholder(ty::PlaceholderType { - universe: next_universe, - bound: bound_ty, - }) + Ty::new_placeholder( + self.tcx, + ty::PlaceholderType { universe: next_universe, bound: bound_ty }, + ) }, consts: &mut |bound_var: ty::BoundVar, ty| { - self.tcx.mk_const( + ty::Const::new_placeholder( + self.tcx, ty::PlaceholderConst { universe: next_universe, bound: bound_var }, ty, ) @@ -103,13 +106,15 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx.replace_bound_vars_uncached(binder, delegate) } - /// See [RegionConstraintCollector::leak_check][1]. + /// See [RegionConstraintCollector::leak_check][1]. We only check placeholder + /// leaking into `outer_universe`, i.e. placeholders which cannot be named by that + /// universe. /// /// [1]: crate::infer::region_constraints::RegionConstraintCollector::leak_check pub fn leak_check( &self, - overly_polymorphic: bool, - snapshot: &CombinedSnapshot<'tcx>, + outer_universe: ty::UniverseIndex, + only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>, ) -> RelateResult<'tcx, ()> { // If the user gave `-Zno-leak-check`, or we have been // configured to skip the leak check, then skip the leak check @@ -117,15 +122,15 @@ impl<'tcx> InferCtxt<'tcx> { // subtyping errors that it would have caught will now be // caught later on, during region checking. However, we // continue to use it for a transition period. - if self.tcx.sess.opts.unstable_opts.no_leak_check || self.skip_leak_check.get() { + if self.tcx.sess.opts.unstable_opts.no_leak_check || self.skip_leak_check { return Ok(()); } self.inner.borrow_mut().unwrap_region_constraints().leak_check( self.tcx, - overly_polymorphic, + outer_universe, self.universe(), - snapshot, + only_consider_snapshot, ) } } diff --git a/compiler/rustc_infer/src/infer/lattice.rs b/compiler/rustc_infer/src/infer/lattice.rs index 7190d33d2..9ef35429f 100644 --- a/compiler/rustc_infer/src/infer/lattice.rs +++ b/compiler/rustc_infer/src/infer/lattice.rs @@ -113,7 +113,7 @@ where | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) if this.define_opaque_types() == DefineOpaqueTypes::Yes && def_id.is_local() - && !this.tcx().trait_solver_next() => + && !this.infcx().next_trait_solver() => { this.register_obligations( infcx diff --git a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs index 8482ae2aa..485e34fe2 100644 --- a/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs +++ b/compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs @@ -347,7 +347,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // name the placeholder, then the placeholder is // larger; otherwise, the only ancestor is `'static`. Err(placeholder) if empty_ui.can_name(placeholder.universe) => { - self.tcx().mk_re_placeholder(placeholder) + ty::Region::new_placeholder(self.tcx(), placeholder) } Err(_) => self.tcx().lifetimes.re_static, }; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index cd99fc312..fca32b73d 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -6,6 +6,7 @@ pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; pub use combine::ObligationEmittingRelation; +use rustc_data_structures::undo_log::UndoLogs; use self::opaque_types::OpaqueTypeStorage; pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; @@ -251,14 +252,13 @@ pub struct InferCtxt<'tcx> { /// solving is left to borrowck instead. pub considering_regions: bool, - pub inner: RefCell>, - /// If set, this flag causes us to skip the 'leak check' during /// higher-ranked subtyping operations. This flag is a temporary one used /// to manage the removal of the leak-check: for the time being, we still run the - /// leak-check, but we issue warnings. This flag can only be set to true - /// when entering a snapshot. - skip_leak_check: Cell, + /// leak-check, but we issue warnings. + skip_leak_check: bool, + + pub inner: RefCell>, /// Once region inference is done, the values for each variable. lexical_region_resolutions: RefCell>>, @@ -298,9 +298,6 @@ pub struct InferCtxt<'tcx> { // FIXME(matthewjasper) Merge into `tainted_by_errors` err_count_on_creation: usize, - /// This flag is true while there is an active snapshot. - in_snapshot: Cell, - /// What is the innermost universe we have created? Starts out as /// `UniverseIndex::root()` but grows from there as we enter /// universal quantifiers. @@ -331,6 +328,8 @@ pub struct InferCtxt<'tcx> { /// there is no type that the user could *actually name* that /// would satisfy it. This avoids crippling inference, basically. pub intercrate: bool, + + next_trait_solver: bool, } /// See the `error_reporting` module for more details. @@ -543,8 +542,12 @@ pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, defining_use_anchor: DefiningAnchor, considering_regions: bool, + skip_leak_check: bool, /// Whether we are in coherence mode. intercrate: bool, + /// Whether we should use the new trait solver in the local inference context, + /// which affects things like which solver is used in `predicate_may_hold`. + next_trait_solver: bool, } pub trait TyCtxtInferExt<'tcx> { @@ -557,7 +560,9 @@ impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { tcx: self, defining_use_anchor: DefiningAnchor::Error, considering_regions: true, + skip_leak_check: false, intercrate: false, + next_trait_solver: self.next_trait_solver_globally(), } } } @@ -574,6 +579,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> { self } + pub fn with_next_trait_solver(mut self, next_trait_solver: bool) -> Self { + self.next_trait_solver = next_trait_solver; + self + } + pub fn intercrate(mut self, intercrate: bool) -> Self { self.intercrate = intercrate; self @@ -584,6 +594,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> { self } + pub fn skip_leak_check(mut self, skip_leak_check: bool) -> Self { + self.skip_leak_check = skip_leak_check; + self + } + /// Given a canonical value `C` as a starting point, create an /// inference context that contains each of the bound values /// within instantiated as a fresh variable. The `f` closure is @@ -605,11 +620,19 @@ impl<'tcx> InferCtxtBuilder<'tcx> { } pub fn build(&mut self) -> InferCtxt<'tcx> { - let InferCtxtBuilder { tcx, defining_use_anchor, considering_regions, intercrate } = *self; + let InferCtxtBuilder { + tcx, + defining_use_anchor, + considering_regions, + skip_leak_check, + intercrate, + next_trait_solver, + } = *self; InferCtxt { tcx, defining_use_anchor, considering_regions, + skip_leak_check, inner: RefCell::new(InferCtxtInner::new()), lexical_region_resolutions: RefCell::new(None), selection_cache: Default::default(), @@ -618,10 +641,9 @@ impl<'tcx> InferCtxtBuilder<'tcx> { reported_closure_mismatch: Default::default(), tainted_by_errors: Cell::new(None), err_count_on_creation: tcx.sess.err_count(), - in_snapshot: Cell::new(false), - skip_leak_check: Cell::new(false), universe: Cell::new(ty::UniverseIndex::ROOT), intercrate, + next_trait_solver, } } } @@ -654,10 +676,13 @@ pub struct CombinedSnapshot<'tcx> { undo_snapshot: Snapshot<'tcx>, region_constraints_snapshot: RegionSnapshot, universe: ty::UniverseIndex, - was_in_snapshot: bool, } impl<'tcx> InferCtxt<'tcx> { + pub fn next_trait_solver(&self) -> bool { + self.next_trait_solver + } + /// Creates a `TypeErrCtxt` for emitting various inference errors. /// During typeck, use `FnCtxt::err_ctxt` instead. pub fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> { @@ -673,10 +698,6 @@ impl<'tcx> InferCtxt<'tcx> { } } - pub fn is_in_snapshot(&self) -> bool { - self.in_snapshot.get() - } - pub fn freshen>>(&self, t: T) -> T { t.fold_with(&mut self.freshener()) } @@ -704,19 +725,19 @@ impl<'tcx> InferCtxt<'tcx> { .type_variables() .unsolved_variables() .into_iter() - .map(|t| self.tcx.mk_ty_var(t)) + .map(|t| Ty::new_var(self.tcx, t)) .collect(); vars.extend( (0..inner.int_unification_table().len()) .map(|i| ty::IntVid { index: i as u32 }) .filter(|&vid| inner.int_unification_table().probe_value(vid).is_none()) - .map(|v| self.tcx.mk_int_var(v)), + .map(|v| Ty::new_int_var(self.tcx, v)), ); vars.extend( (0..inner.float_unification_table().len()) .map(|i| ty::FloatVid { index: i as u32 }) .filter(|&vid| inner.float_unification_table().probe_value(vid).is_none()) - .map(|v| self.tcx.mk_float_var(v)), + .map(|v| Ty::new_float_var(self.tcx, v)), ); vars } @@ -737,31 +758,30 @@ impl<'tcx> InferCtxt<'tcx> { } } + pub fn in_snapshot(&self) -> bool { + UndoLogs::>::in_snapshot(&self.inner.borrow_mut().undo_log) + } + + pub fn num_open_snapshots(&self) -> usize { + UndoLogs::>::num_open_snapshots(&self.inner.borrow_mut().undo_log) + } + fn start_snapshot(&self) -> CombinedSnapshot<'tcx> { debug!("start_snapshot()"); - let in_snapshot = self.in_snapshot.replace(true); - let mut inner = self.inner.borrow_mut(); CombinedSnapshot { undo_snapshot: inner.undo_log.start_snapshot(), region_constraints_snapshot: inner.unwrap_region_constraints().start_snapshot(), universe: self.universe(), - was_in_snapshot: in_snapshot, } } #[instrument(skip(self, snapshot), level = "debug")] fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'tcx>) { - let CombinedSnapshot { - undo_snapshot, - region_constraints_snapshot, - universe, - was_in_snapshot, - } = snapshot; - - self.in_snapshot.set(was_in_snapshot); + let CombinedSnapshot { undo_snapshot, region_constraints_snapshot, universe } = snapshot; + self.universe.set(universe); let mut inner = self.inner.borrow_mut(); @@ -771,14 +791,8 @@ impl<'tcx> InferCtxt<'tcx> { #[instrument(skip(self, snapshot), level = "debug")] fn commit_from(&self, snapshot: CombinedSnapshot<'tcx>) { - let CombinedSnapshot { - undo_snapshot, - region_constraints_snapshot: _, - universe: _, - was_in_snapshot, - } = snapshot; - - self.in_snapshot.set(was_in_snapshot); + let CombinedSnapshot { undo_snapshot, region_constraints_snapshot: _, universe: _ } = + snapshot; self.inner.borrow_mut().commit(undo_snapshot); } @@ -815,32 +829,9 @@ impl<'tcx> InferCtxt<'tcx> { r } - /// If `should_skip` is true, then execute `f` then unroll any bindings it creates. - #[instrument(skip(self, f), level = "debug")] - pub fn probe_maybe_skip_leak_check(&self, should_skip: bool, f: F) -> R - where - F: FnOnce(&CombinedSnapshot<'tcx>) -> R, - { - let snapshot = self.start_snapshot(); - let was_skip_leak_check = self.skip_leak_check.get(); - if should_skip { - self.skip_leak_check.set(true); - } - let r = f(&snapshot); - self.rollback_to("probe", snapshot); - self.skip_leak_check.set(was_skip_leak_check); - r - } - - /// Scan the constraints produced since `snapshot` began and returns: - /// - /// - `None` -- if none of them involves "region outlives" constraints. - /// - `Some(true)` -- if there are `'a: 'b` constraints where `'a` or `'b` is a placeholder. - /// - `Some(false)` -- if there are `'a: 'b` constraints but none involve placeholders. - pub fn region_constraints_added_in_snapshot( - &self, - snapshot: &CombinedSnapshot<'tcx>, - ) -> Option { + /// Scan the constraints produced since `snapshot` and check whether + /// we added any region constraints. + pub fn region_constraints_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'tcx>) -> bool { self.inner .borrow_mut() .unwrap_region_constraints() @@ -987,7 +978,7 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { - self.tcx.mk_ty_var(self.next_ty_var_id(origin)) + Ty::new_var(self.tcx, self.next_ty_var_id(origin)) } pub fn next_ty_var_id_in_universe( @@ -1004,11 +995,11 @@ impl<'tcx> InferCtxt<'tcx> { universe: ty::UniverseIndex, ) -> Ty<'tcx> { let vid = self.next_ty_var_id_in_universe(origin, universe); - self.tcx.mk_ty_var(vid) + Ty::new_var(self.tcx, vid) } pub fn next_const_var(&self, ty: Ty<'tcx>, origin: ConstVariableOrigin) -> ty::Const<'tcx> { - self.tcx.mk_const(self.next_const_var_id(origin), ty) + ty::Const::new_var(self.tcx, self.next_const_var_id(origin), ty) } pub fn next_const_var_in_universe( @@ -1022,7 +1013,7 @@ impl<'tcx> InferCtxt<'tcx> { .borrow_mut() .const_unification_table() .new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } }); - self.tcx.mk_const(vid, ty) + ty::Const::new_var(self.tcx, vid, ty) } pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid<'tcx> { @@ -1037,7 +1028,7 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn next_int_var(&self) -> Ty<'tcx> { - self.tcx.mk_int_var(self.next_int_var_id()) + Ty::new_int_var(self.tcx, self.next_int_var_id()) } fn next_float_var_id(&self) -> FloatVid { @@ -1045,7 +1036,7 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn next_float_var(&self) -> Ty<'tcx> { - self.tcx.mk_float_var(self.next_float_var_id()) + Ty::new_float_var(self.tcx, self.next_float_var_id()) } /// Creates a fresh region variable with the next available index. @@ -1065,7 +1056,7 @@ impl<'tcx> InferCtxt<'tcx> { ) -> ty::Region<'tcx> { let region_var = self.inner.borrow_mut().unwrap_region_constraints().new_region_var(universe, origin); - self.tcx.mk_re_var(region_var) + ty::Region::new_var(self.tcx, region_var) } /// Return the universe that the region `r` was created in. For @@ -1119,13 +1110,13 @@ impl<'tcx> InferCtxt<'tcx> { TypeVariableOrigin { kind: TypeVariableOriginKind::TypeParameterDefinition( param.name, - Some(param.def_id), + param.def_id, ), span, }, ); - self.tcx.mk_ty_var(ty_var_id).into() + Ty::new_var(self.tcx, ty_var_id).into() } GenericParamDefKind::Const { .. } => { let origin = ConstVariableOrigin { @@ -1140,15 +1131,15 @@ impl<'tcx> InferCtxt<'tcx> { origin, val: ConstVariableValue::Unknown { universe: self.universe() }, }); - self.tcx - .mk_const( - const_var_id, - self.tcx - .type_of(param.def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"), - ) - .into() + ty::Const::new_var( + self.tcx, + const_var_id, + self.tcx + .type_of(param.def_id) + .no_bound_vars() + .expect("const parameter types cannot be generic"), + ) + .into() } } } @@ -1206,15 +1197,15 @@ impl<'tcx> InferCtxt<'tcx> { .var_origin(vid) } - /// Takes ownership of the list of variable regions. This implies - /// that all the region constraints have already been taken, and - /// hence that `resolve_regions_and_report_errors` can never be - /// called. This is used only during NLL processing to "hand off" ownership - /// of the set of region variables into the NLL region context. + /// Clone the list of variable regions. This is used only during NLL processing + /// to put the set of region variables into the NLL region context. pub fn get_region_var_origins(&self) -> VarInfos { let mut inner = self.inner.borrow_mut(); let (var_infos, data) = inner .region_constraint_storage + // We clone instead of taking because borrowck still wants to use + // the inference context after calling this for diagnostics + // and the new trait solver. .clone() .expect("regions already resolved") .with_log(&mut inner.undo_log) @@ -1274,7 +1265,7 @@ impl<'tcx> InferCtxt<'tcx> { if let Some(value) = inner.int_unification_table().probe_value(vid) { value.to_type(self.tcx) } else { - self.tcx.mk_int_var(inner.int_unification_table().find(vid)) + Ty::new_int_var(self.tcx, inner.int_unification_table().find(vid)) } } @@ -1285,7 +1276,7 @@ impl<'tcx> InferCtxt<'tcx> { if let Some(value) = inner.float_unification_table().probe_value(vid) { value.to_type(self.tcx) } else { - self.tcx.mk_float_var(inner.float_unification_table().find(vid)) + Ty::new_float_var(self.tcx, inner.float_unification_table().find(vid)) } } @@ -1468,6 +1459,7 @@ impl<'tcx> InferCtxt<'tcx> { /// universes. Updates `self.universe` to that new universe. pub fn create_next_universe(&self) -> ty::UniverseIndex { let u = self.universe.get().next_universe(); + debug!("create_next_universe {u:?}"); self.universe.set(u); u } @@ -1480,7 +1472,7 @@ impl<'tcx> InferCtxt<'tcx> { span: Option, ) -> Result, ErrorHandled> { match self.const_eval_resolve(param_env, unevaluated, span) { - Ok(Some(val)) => Ok(self.tcx.mk_const(val, ty)), + Ok(Some(val)) => Ok(ty::Const::new_value(self.tcx, val, ty)), Ok(None) => { let tcx = self.tcx; let def_id = unevaluated.def; @@ -1953,13 +1945,16 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>( self.idx += 1; idx }; - self.tcx.mk_placeholder(ty::PlaceholderType { - universe: ty::UniverseIndex::ROOT, - bound: ty::BoundTy { - var: ty::BoundVar::from_u32(idx), - kind: ty::BoundTyKind::Anon, + Ty::new_placeholder( + self.tcx, + ty::PlaceholderType { + universe: ty::UniverseIndex::ROOT, + bound: ty::BoundTy { + var: ty::BoundVar::from_u32(idx), + kind: ty::BoundTyKind::Anon, + }, }, - }) + ) } else { t.super_fold_with(self) } @@ -1972,7 +1967,8 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>( if ty.has_non_region_param() || ty.has_non_region_infer() { bug!("const `{c}`'s type should not reference params or types"); } - self.tcx.mk_const( + ty::Const::new_placeholder( + self.tcx, ty::PlaceholderConst { universe: ty::UniverseIndex::ROOT, bound: ty::BoundVar::from_u32({ diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs index d3fd01b96..71c07f31b 100644 --- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs +++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs @@ -491,12 +491,12 @@ where ( &ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, .. }), &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }), - ) if a_def_id == b_def_id || infcx.tcx.trait_solver_next() => { + ) if a_def_id == b_def_id || infcx.next_trait_solver() => { infcx.super_combine_tys(self, a, b).or_else(|err| { // This behavior is only there for the old solver, the new solver // shouldn't ever fail. Instead, it unconditionally emits an // alias-relate goal. - assert!(!self.tcx().trait_solver_next()); + assert!(!self.infcx.next_trait_solver()); self.tcx().sess.delay_span_bug( self.delegate.span(), "failure to relate an opaque to itself should result in an error later on", @@ -506,7 +506,7 @@ where } (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) - if def_id.is_local() && !self.tcx().trait_solver_next() => + if def_id.is_local() && !self.infcx.next_trait_solver() => { self.relate_opaques(a, b) } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 9d5ec228d..5927f79a1 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -33,9 +33,6 @@ pub struct OpaqueTypeDecl<'tcx> { /// There can be multiple, but they are all `lub`ed together at the end /// to obtain the canonical hidden type. pub hidden_type: OpaqueHiddenType<'tcx>, - - /// The origin of the opaque type. - pub origin: hir::OpaqueTyOrigin, } impl<'tcx> InferCtxt<'tcx> { @@ -49,7 +46,7 @@ impl<'tcx> InferCtxt<'tcx> { param_env: ty::ParamEnv<'tcx>, ) -> InferOk<'tcx, T> { // We handle opaque types differently in the new solver. - if self.tcx.trait_solver_next() { + if self.next_trait_solver() { return InferOk { value, obligations: vec![] }; } @@ -108,7 +105,7 @@ impl<'tcx> InferCtxt<'tcx> { let process = |a: Ty<'tcx>, b: Ty<'tcx>, a_is_expected| match *a.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) if def_id.is_local() => { let def_id = def_id.expect_local(); - let origin = match self.defining_use_anchor { + match self.defining_use_anchor { DefiningAnchor::Bind(_) => { // Check that this is `impl Trait` type is // declared by `parent_def_id` -- i.e., one whose @@ -144,9 +141,11 @@ impl<'tcx> InferCtxt<'tcx> { // let x = || foo(); // returns the Opaque assoc with `foo` // } // ``` - self.opaque_type_origin(def_id)? + if self.opaque_type_origin(def_id).is_none() { + return None; + } } - DefiningAnchor::Bubble => self.opaque_type_origin_unchecked(def_id), + DefiningAnchor::Bubble => {} DefiningAnchor::Error => return None, }; if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() { @@ -170,7 +169,6 @@ impl<'tcx> InferCtxt<'tcx> { cause.clone(), param_env, b, - origin, a_is_expected, )) } @@ -380,7 +378,7 @@ impl<'tcx> InferCtxt<'tcx> { DefiningAnchor::Bind(bind) => bind, }; - let origin = self.opaque_type_origin_unchecked(def_id); + let origin = self.tcx.opaque_type_origin(def_id); let in_definition_scope = match origin { // Async `impl Trait` hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id, @@ -397,13 +395,6 @@ impl<'tcx> InferCtxt<'tcx> { }; in_definition_scope.then_some(origin) } - - /// Returns the origin of the opaque type `def_id` even if we are not in its - /// defining scope. - #[instrument(skip(self), level = "trace", ret)] - fn opaque_type_origin_unchecked(&self, def_id: LocalDefId) -> OpaqueTyOrigin { - self.tcx.hir().expect_item(def_id).expect_opaque_ty().origin - } } /// Visitor that requires that (almost) all regions in the type visited outlive @@ -482,17 +473,6 @@ where } } - ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => { - // Skip lifetime parameters that are not captures. - let variances = self.tcx.variances_of(proj.def_id); - - for (v, s) in std::iter::zip(variances, proj.substs.iter()) { - if *v != ty::Variance::Bivariant { - s.visit_with(self); - } - } - } - _ => { ty.super_visit_with(self); } @@ -524,30 +504,22 @@ impl<'tcx> InferCtxt<'tcx> { cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, - origin: hir::OpaqueTyOrigin, a_is_expected: bool, ) -> InferResult<'tcx, ()> { - // Ideally, we'd get the span where *this specific `ty` came - // from*, but right now we just use the span from the overall - // value being folded. In simple cases like `-> impl Foo`, - // these are the same span, but not in cases like `-> (impl - // Foo, impl Bar)`. - let span = cause.span; - let prev = self.inner.borrow_mut().opaque_types().register( + let mut obligations = Vec::new(); + + self.insert_hidden_type( opaque_type_key, - OpaqueHiddenType { ty: hidden_ty, span }, - origin, - ); - let mut obligations = if let Some(prev) = prev { - self.at(&cause, param_env) - .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)? - .obligations - } else { - Vec::new() - }; + &cause, + param_env, + hidden_ty, + a_is_expected, + &mut obligations, + )?; self.add_item_bounds_for_hidden_type( - opaque_type_key, + opaque_type_key.def_id.to_def_id(), + opaque_type_key.substs, cause, param_env, hidden_ty, @@ -557,32 +529,60 @@ impl<'tcx> InferCtxt<'tcx> { Ok(InferOk { value: (), obligations }) } - /// Registers an opaque's hidden type -- only should be used when the opaque - /// can be defined. For something more fallible -- checks the anchors, tries - /// to unify opaques in both dirs, etc. -- use `InferCtxt::handle_opaque_type`. - pub fn register_hidden_type_in_new_solver( + /// Insert a hidden type into the opaque type storage, equating it + /// with any previous entries if necessary. + /// + /// This **does not** add the item bounds of the opaque as nested + /// obligations. That is only necessary when normalizing the opaque + /// itself, not when getting the opaque type constraints from + /// somewhere else. + pub fn insert_hidden_type( &self, opaque_type_key: OpaqueTypeKey<'tcx>, + cause: &ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, - ) -> InferResult<'tcx, ()> { - assert!(self.tcx.trait_solver_next()); - let origin = self - .opaque_type_origin(opaque_type_key.def_id) - .expect("should be called for defining usages only"); - self.register_hidden_type( - opaque_type_key, - ObligationCause::dummy(), - param_env, - hidden_ty, - origin, - true, - ) + a_is_expected: bool, + obligations: &mut Vec>, + ) -> Result<(), TypeError<'tcx>> { + // Ideally, we'd get the span where *this specific `ty` came + // from*, but right now we just use the span from the overall + // value being folded. In simple cases like `-> impl Foo`, + // these are the same span, but not in cases like `-> (impl + // Foo, impl Bar)`. + let span = cause.span; + if self.intercrate { + // During intercrate we do not define opaque types but instead always + // force ambiguity unless the hidden type is known to not implement + // our trait. + obligations.push(traits::Obligation::new( + self.tcx, + cause.clone(), + param_env, + ty::PredicateKind::Ambiguous, + )) + } else { + let prev = self + .inner + .borrow_mut() + .opaque_types() + .register(opaque_type_key, OpaqueHiddenType { ty: hidden_ty, span }); + if let Some(prev) = prev { + obligations.extend( + self.at(&cause, param_env) + .eq_exp(DefineOpaqueTypes::Yes, a_is_expected, prev, hidden_ty)? + .obligations, + ); + } + }; + + Ok(()) } pub fn add_item_bounds_for_hidden_type( &self, - OpaqueTypeKey { def_id, substs }: OpaqueTypeKey<'tcx>, + def_id: DefId, + substs: ty::SubstsRef<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, hidden_ty: Ty<'tcx>, @@ -602,7 +602,7 @@ impl<'tcx> InferCtxt<'tcx> { ty::Alias(ty::Projection, projection_ty) if !projection_ty.has_escaping_bound_vars() && !tcx.is_impl_trait_in_trait(projection_ty.def_id) - && !tcx.trait_solver_next() => + && !self.next_trait_solver() => { self.infer_projection( param_env, @@ -615,7 +615,7 @@ impl<'tcx> InferCtxt<'tcx> { // Replace all other mentions of the same opaque type with the hidden type, // as the bounds must hold on the hidden type after all. ty::Alias(ty::Opaque, ty::AliasTy { def_id: def_id2, substs: substs2, .. }) - if def_id.to_def_id() == def_id2 && substs == substs2 => + if def_id == def_id2 && substs == substs2 => { hidden_ty } @@ -624,16 +624,14 @@ impl<'tcx> InferCtxt<'tcx> { ty::Alias( ty::Projection, ty::AliasTy { def_id: def_id2, substs: substs2, .. }, - ) if def_id.to_def_id() == def_id2 && substs == substs2 => hidden_ty, + ) if def_id == def_id2 && substs == substs2 => hidden_ty, _ => ty, }, lt_op: |lt| lt, ct_op: |ct| ct, }); - if let ty::PredicateKind::Clause(ty::Clause::Projection(projection)) = - predicate.kind().skip_binder() - { + if let ty::ClauseKind::Projection(projection) = predicate.kind().skip_binder() { if projection.term.references_error() { // No point on adding any obligations since there's a type error involved. obligations.clear(); diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs index a0f6d7eca..a737761ba 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/table.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs @@ -1,5 +1,4 @@ use rustc_data_structures::undo_log::UndoLogs; -use rustc_hir::OpaqueTyOrigin; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty}; use rustc_span::DUMMY_SP; @@ -60,14 +59,13 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> { &mut self, key: OpaqueTypeKey<'tcx>, hidden_type: OpaqueHiddenType<'tcx>, - origin: OpaqueTyOrigin, ) -> Option> { if let Some(decl) = self.storage.opaque_types.get_mut(&key) { let prev = std::mem::replace(&mut decl.hidden_type, hidden_type); self.undo_log.push(UndoLog::OpaqueTypes(key, Some(prev))); return Some(prev.ty); } - let decl = OpaqueTypeDecl { hidden_type, origin }; + let decl = OpaqueTypeDecl { hidden_type }; self.storage.opaque_types.insert(key, decl); self.undo_log.push(UndoLog::OpaqueTypes(key, None)); None diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs index 8a44d5031..cb92fc6dd 100644 --- a/compiler/rustc_infer/src/infer/outlives/mod.rs +++ b/compiler/rustc_infer/src/infer/outlives/mod.rs @@ -20,27 +20,18 @@ pub fn explicit_outlives_bounds<'tcx>( param_env .caller_bounds() .into_iter() - .map(ty::Predicate::kind) + .map(ty::Clause::kind) .filter_map(ty::Binder::no_bound_vars) .filter_map(move |kind| match kind { - ty::PredicateKind::Clause(ty::Clause::Projection(..)) - | ty::PredicateKind::Clause(ty::Clause::Trait(..)) - | ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) - | ty::PredicateKind::AliasRelate(..) - | ty::PredicateKind::Coerce(..) - | ty::PredicateKind::Subtype(..) - | ty::PredicateKind::WellFormed(..) - | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) - | ty::PredicateKind::ConstEvaluatable(..) - | ty::PredicateKind::ConstEquate(..) - | ty::PredicateKind::Ambiguous - | ty::PredicateKind::TypeWellFormedFromEnv(..) => None, - ty::PredicateKind::Clause(ty::Clause::RegionOutlives(ty::OutlivesPredicate( - r_a, - r_b, - ))) => Some(OutlivesBound::RegionSubRegion(r_b, r_a)), + ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => { + Some(OutlivesBound::RegionSubRegion(r_b, r_a)) + } + ty::ClauseKind::Trait(_) + | ty::ClauseKind::TypeOutlives(_) + | ty::ClauseKind::Projection(_) + | ty::ClauseKind::ConstArgHasType(_, _) + | ty::ClauseKind::WellFormed(_) + | ty::ClauseKind::ConstEvaluatable(_) => None, }) } diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 9c20c814b..73df6d03f 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -125,10 +125,7 @@ impl<'tcx> InferCtxt<'tcx> { /// right before lexical region resolution. #[instrument(level = "debug", skip(self, outlives_env))] pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvironment<'tcx>) { - assert!( - !self.in_snapshot.get(), - "cannot process registered region obligations in a snapshot" - ); + assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); let my_region_obligations = self.take_registered_region_obligations(); diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index c2bf0f3db..1a5e2b520 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -223,7 +223,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // parameter environments are already elaborated, so we don't // have to worry about that. let c_b = self.param_env.caller_bounds(); - let param_bounds = self.collect_outlives_from_predicate_list(erased_ty, c_b.into_iter()); + let param_bounds = self.collect_outlives_from_clause_list(erased_ty, c_b.into_iter()); // Next, collect regions we scraped from the well-formedness // constraints in the fn signature. To do that, we walk the list @@ -293,10 +293,10 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { ) -> impl Iterator> { let tcx = self.tcx; let bounds = tcx.item_bounds(alias_ty.def_id); - trace!("{:#?}", bounds.0); + trace!("{:#?}", bounds.skip_binder()); bounds .subst_iter(tcx, alias_ty.substs) - .filter_map(|p| p.to_opt_type_outlives()) + .filter_map(|p| p.as_type_outlives_clause()) .filter_map(|p| p.no_bound_vars()) .map(|OutlivesPredicate(_, r)| r) } @@ -307,15 +307,15 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { /// when comparing `ty` for equality, so `ty` must be something /// that does not involve inference variables and where you /// otherwise want a precise match. - fn collect_outlives_from_predicate_list( + fn collect_outlives_from_clause_list( &self, erased_ty: Ty<'tcx>, - predicates: impl Iterator>, + clauses: impl Iterator>, ) -> impl Iterator, ty::Region<'tcx>>>> { let tcx = self.tcx; let param_env = self.param_env; - predicates.filter_map(|p| p.to_opt_type_outlives()).filter(move |outlives_predicate| { + clauses.filter_map(|p| p.as_type_outlives_clause()).filter(move |outlives_predicate| { super::test_type_match::can_match_erased_ty( tcx, param_env, diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index fa6529dfa..38e74e538 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -21,28 +21,18 @@ impl<'tcx> InferCtxt<'tcx> { recursion_depth: usize, obligations: &mut Vec>, ) -> Ty<'tcx> { - if self.tcx.trait_solver_next() { - // FIXME(-Ztrait-solver=next): Instead of branching here, - // completely change the normalization routine with the new solver. - // - // The new solver correctly handles projection equality so this hack - // is not necessary. if re-enabled it should emit `PredicateKind::AliasRelate` - // not `PredicateKind::Clause(Clause::Projection(..))` as in the new solver - // `Projection` is used as `normalizes-to` which will fail for `::Assoc eq ?0`. - return projection_ty.to_ty(self.tcx); - } else { - let def_id = projection_ty.def_id; - let ty_var = self.next_ty_var(TypeVariableOrigin { - kind: TypeVariableOriginKind::NormalizeProjectionType, - span: self.tcx.def_span(def_id), - }); - let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection( - ty::ProjectionPredicate { projection_ty, term: ty_var.into() }, - ))); - let obligation = - Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection); - obligations.push(obligation); - ty_var - } + debug_assert!(!self.next_trait_solver()); + let def_id = projection_ty.def_id; + let ty_var = self.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::NormalizeProjectionType, + span: self.tcx.def_span(def_id), + }); + let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Projection( + ty::ProjectionPredicate { projection_ty, term: ty_var.into() }, + ))); + let obligation = + Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection); + obligations.push(obligation); + ty_var } } diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs index 89cfc9ea3..dd65f66cc 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs @@ -3,7 +3,6 @@ use crate::infer::CombinedSnapshot; use rustc_data_structures::{ fx::FxIndexMap, graph::{scc::Sccs, vec_graph::VecGraph}, - undo_log::UndoLogs, }; use rustc_index::Idx; use rustc_middle::ty::error::TypeError; @@ -13,7 +12,9 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// Searches new universes created during `snapshot`, looking for /// placeholders that may "leak" out from the universes they are contained /// in. If any leaking placeholders are found, then an `Err` is returned - /// (typically leading to the snapshot being reversed). + /// (typically leading to the snapshot being reversed). This algorithm + /// only looks at placeholders which cannot be named by `outer_universe`, + /// as this is the universe we're currently checking for a leak. /// /// The leak check *used* to be the only way we had to handle higher-ranked /// obligations. Now that we have integrated universes into the region @@ -55,6 +56,12 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// * if they must also be equal to a placeholder P, and U cannot name P, report an error, as that /// indicates `P: R` and `R` is in an incompatible universe /// + /// To improve performance and for the old trait solver caching to be sound, this takes + /// an optional snapshot in which case we only look at region constraints added in that + /// snapshot. If we were to not do that the `leak_check` during evaluation can rely on + /// region constraints added outside of that evaluation. As that is not reflected in the + /// cache key this would be unsound. + /// /// # Historical note /// /// Older variants of the leak check used to report errors for these @@ -62,36 +69,21 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { /// /// * R: P1, even if R cannot name P1, because R = 'static is a valid sol'n /// * R: P1, R: P2, as above + #[instrument(level = "debug", skip(self, tcx, only_consider_snapshot), ret)] pub fn leak_check( &mut self, tcx: TyCtxt<'tcx>, - overly_polymorphic: bool, + outer_universe: ty::UniverseIndex, max_universe: ty::UniverseIndex, - snapshot: &CombinedSnapshot<'tcx>, + only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>, ) -> RelateResult<'tcx, ()> { - debug!( - "leak_check(max_universe={:?}, snapshot.universe={:?}, overly_polymorphic={:?})", - max_universe, snapshot.universe, overly_polymorphic - ); - - assert!(UndoLogs::>::in_snapshot(&self.undo_log)); - - let universe_at_start_of_snapshot = snapshot.universe; - if universe_at_start_of_snapshot == max_universe { + if outer_universe == max_universe { return Ok(()); } - let mini_graph = - &MiniGraph::new(tcx, self.undo_log.region_constraints(), &self.storage.data.verifys); + let mini_graph = &MiniGraph::new(tcx, &self, only_consider_snapshot); - let mut leak_check = LeakCheck::new( - tcx, - universe_at_start_of_snapshot, - max_universe, - overly_polymorphic, - mini_graph, - self, - ); + let mut leak_check = LeakCheck::new(tcx, outer_universe, max_universe, mini_graph, self); leak_check.assign_placeholder_values()?; leak_check.propagate_scc_value()?; Ok(()) @@ -100,9 +92,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { struct LeakCheck<'me, 'tcx> { tcx: TyCtxt<'tcx>, - universe_at_start_of_snapshot: ty::UniverseIndex, - /// Only used when reporting region errors. - overly_polymorphic: bool, + outer_universe: ty::UniverseIndex, mini_graph: &'me MiniGraph<'tcx>, rcc: &'me RegionConstraintCollector<'me, 'tcx>, @@ -130,17 +120,15 @@ struct LeakCheck<'me, 'tcx> { impl<'me, 'tcx> LeakCheck<'me, 'tcx> { fn new( tcx: TyCtxt<'tcx>, - universe_at_start_of_snapshot: ty::UniverseIndex, + outer_universe: ty::UniverseIndex, max_universe: ty::UniverseIndex, - overly_polymorphic: bool, mini_graph: &'me MiniGraph<'tcx>, rcc: &'me RegionConstraintCollector<'me, 'tcx>, ) -> Self { let dummy_scc_universe = SccUniverse { universe: max_universe, region: None }; Self { tcx, - universe_at_start_of_snapshot, - overly_polymorphic, + outer_universe, mini_graph, rcc, scc_placeholders: IndexVec::from_elem_n(None, mini_graph.sccs.num_sccs()), @@ -165,7 +153,7 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> { // Detect those SCCs that directly contain a placeholder if let ty::RePlaceholder(placeholder) = **region { - if self.universe_at_start_of_snapshot.cannot_name(placeholder.universe) { + if self.outer_universe.cannot_name(placeholder.universe) { self.assign_scc_value(scc, placeholder)?; } } @@ -280,7 +268,7 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> { placeholder1: ty::PlaceholderRegion, placeholder2: ty::PlaceholderRegion, ) -> TypeError<'tcx> { - self.error(placeholder1, self.tcx.mk_re_placeholder(placeholder2)) + self.error(placeholder1, ty::Region::new_placeholder(self.tcx, placeholder2)) } fn error( @@ -289,11 +277,7 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> { other_region: ty::Region<'tcx>, ) -> TypeError<'tcx> { debug!("error: placeholder={:?}, other_region={:?}", placeholder, other_region); - if self.overly_polymorphic { - TypeError::RegionsOverlyPolymorphic(placeholder.bound.kind, other_region) - } else { - TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound.kind, other_region) - } + TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound.kind, other_region) } } @@ -379,56 +363,70 @@ struct MiniGraph<'tcx> { } impl<'tcx> MiniGraph<'tcx> { - fn new<'a>( + fn new( tcx: TyCtxt<'tcx>, - undo_log: impl Iterator>, - verifys: &[Verify<'tcx>], - ) -> Self - where - 'tcx: 'a, - { + region_constraints: &RegionConstraintCollector<'_, 'tcx>, + only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>, + ) -> Self { let mut nodes = FxIndexMap::default(); let mut edges = Vec::new(); // Note that if `R2: R1`, we get a callback `r1, r2`, so `target` is first parameter. - Self::iterate_undo_log(tcx, undo_log, verifys, |target, source| { - let source_node = Self::add_node(&mut nodes, source); - let target_node = Self::add_node(&mut nodes, target); - edges.push((source_node, target_node)); - }); + Self::iterate_region_constraints( + tcx, + region_constraints, + only_consider_snapshot, + |target, source| { + let source_node = Self::add_node(&mut nodes, source); + let target_node = Self::add_node(&mut nodes, target); + edges.push((source_node, target_node)); + }, + ); let graph = VecGraph::new(nodes.len(), edges); let sccs = Sccs::new(&graph); Self { nodes, sccs } } /// Invokes `each_edge(R1, R2)` for each edge where `R2: R1` - fn iterate_undo_log<'a>( + fn iterate_region_constraints( tcx: TyCtxt<'tcx>, - undo_log: impl Iterator>, - verifys: &[Verify<'tcx>], + region_constraints: &RegionConstraintCollector<'_, 'tcx>, + only_consider_snapshot: Option<&CombinedSnapshot<'tcx>>, mut each_edge: impl FnMut(ty::Region<'tcx>, ty::Region<'tcx>), - ) where - 'tcx: 'a, - { - for undo_entry in undo_log { - match undo_entry { - &AddConstraint(Constraint::VarSubVar(a, b)) => { - each_edge(tcx.mk_re_var(a), tcx.mk_re_var(b)); - } - &AddConstraint(Constraint::RegSubVar(a, b)) => { - each_edge(a, tcx.mk_re_var(b)); - } - &AddConstraint(Constraint::VarSubReg(a, b)) => { - each_edge(tcx.mk_re_var(a), b); - } - &AddConstraint(Constraint::RegSubReg(a, b)) => { - each_edge(a, b); + ) { + let mut each_constraint = |constraint| match constraint { + &Constraint::VarSubVar(a, b) => { + each_edge(ty::Region::new_var(tcx, a), ty::Region::new_var(tcx, b)); + } + &Constraint::RegSubVar(a, b) => { + each_edge(a, ty::Region::new_var(tcx, b)); + } + &Constraint::VarSubReg(a, b) => { + each_edge(ty::Region::new_var(tcx, a), b); + } + &Constraint::RegSubReg(a, b) => { + each_edge(a, b); + } + }; + + if let Some(snapshot) = only_consider_snapshot { + for undo_entry in + region_constraints.undo_log.region_constraints_in_snapshot(&snapshot.undo_snapshot) + { + match undo_entry { + AddConstraint(constraint) => { + each_constraint(constraint); + } + &AddVerify(i) => span_bug!( + region_constraints.data().verifys[i].origin.span(), + "we never add verifications while doing higher-ranked things", + ), + &AddCombination(..) | &AddVar(..) => {} } - &AddVerify(i) => span_bug!( - verifys[i].origin.span(), - "we never add verifications while doing higher-ranked things", - ), - &AddCombination(..) | &AddVar(..) => {} + } + } else { + for (constraint, _origin) in ®ion_constraints.data().constraints { + each_constraint(constraint) } } } diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index c7a307b89..613da8a0b 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -400,7 +400,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { data } - pub(super) fn data(&self) -> &RegionConstraintData<'tcx> { + pub fn data(&self) -> &RegionConstraintData<'tcx> { &self.data } @@ -610,13 +610,13 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { let resolved = ut .probe_value(root_vid) .get_value_ignoring_universes() - .unwrap_or_else(|| tcx.mk_re_var(root_vid)); + .unwrap_or_else(|| ty::Region::new_var(tcx, root_vid)); // Don't resolve a variable to a region that it cannot name. if self.var_universe(vid).can_name(self.universe(resolved)) { resolved } else { - tcx.mk_re_var(vid) + ty::Region::new_var(tcx, vid) } } @@ -637,7 +637,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { ) -> Region<'tcx> { let vars = TwoRegions { a, b }; if let Some(&c) = self.combine_map(t).get(&vars) { - return tcx.mk_re_var(c); + return ty::Region::new_var(tcx, c); } let a_universe = self.universe(a); let b_universe = self.universe(b); @@ -645,7 +645,7 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { let c = self.new_region_var(c_universe, MiscVariable(origin.span())); self.combine_map(t).insert(vars, c); self.undo_log.push(AddCombination(t, vars)); - let new_r = tcx.mk_re_var(c); + let new_r = ty::Region::new_var(tcx, c); for old_r in [a, b] { match t { Glb => self.make_subregion(origin.clone(), new_r, old_r), @@ -683,15 +683,10 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> { } /// See `InferCtxt::region_constraints_added_in_snapshot`. - pub fn region_constraints_added_in_snapshot(&self, mark: &Snapshot<'tcx>) -> Option { + pub fn region_constraints_added_in_snapshot(&self, mark: &Snapshot<'tcx>) -> bool { self.undo_log .region_constraints_in_snapshot(mark) - .map(|&elt| match elt { - AddConstraint(constraint) => Some(constraint.involves_placeholders()), - _ => None, - }) - .max() - .unwrap_or(None) + .any(|&elt| matches!(elt, AddConstraint(_))) } #[inline] diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index ceafafb55..27e1ed56f 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -118,7 +118,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { (&ty::Error(e), _) | (_, &ty::Error(e)) => { infcx.set_tainted_by_errors(e); - Ok(self.tcx().ty_error(e)) + Ok(Ty::new_error(self.tcx(), e)) } ( @@ -132,7 +132,7 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { | (_, &ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. })) if self.fields.define_opaque_types == DefineOpaqueTypes::Yes && def_id.is_local() - && !self.tcx().trait_solver_next() => + && !self.fields.infcx.next_trait_solver() => { self.fields.obligations.extend( infcx diff --git a/compiler/rustc_infer/src/infer/type_variable.rs b/compiler/rustc_infer/src/infer/type_variable.rs index f7ab05b2d..01c11d163 100644 --- a/compiler/rustc_infer/src/infer/type_variable.rs +++ b/compiler/rustc_infer/src/infer/type_variable.rs @@ -123,13 +123,12 @@ pub enum TypeVariableOriginKind { NormalizeProjectionType, TypeInference, OpaqueTypeInference(DefId), - TypeParameterDefinition(Symbol, Option), + TypeParameterDefinition(Symbol, DefId), /// One of the upvars or closure kind parameters in a `ClosureSubsts` /// (before it has been determined). // FIXME(eddyb) distinguish upvar inference variables from the rest. ClosureSynthetic, - SubstitutionPlaceholder, AutoDeref, AdjustmentType, diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index 955c54e85..25d06b21e 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -138,11 +138,9 @@ impl<'tcx> InferCtxtInner<'tcx> { } if self.undo_log.num_open_snapshots == 1 { - // The root snapshot. It's safe to clear the undo log because - // there's no snapshot further out that we might need to roll back - // to. + // After the root snapshot the undo log should be empty. assert!(snapshot.undo_len == 0); - self.undo_log.logs.clear(); + assert!(self.undo_log.logs.is_empty()); } self.undo_log.num_open_snapshots -= 1; @@ -183,15 +181,6 @@ impl<'tcx> InferCtxtUndoLogs<'tcx> { self.logs[s.undo_len..].iter().any(|log| matches!(log, UndoLog::OpaqueTypes(..))) } - pub(crate) fn region_constraints( - &self, - ) -> impl Iterator> + Clone { - self.logs.iter().filter_map(|log| match log { - UndoLog::RegionConstraintCollector(log) => Some(log), - _ => None, - }) - } - fn assert_open_snapshot(&self, snapshot: &Snapshot<'tcx>) { // Failures here may indicate a failure to follow a stack discipline. assert!(self.logs.len() >= snapshot.undo_len); diff --git a/compiler/rustc_infer/src/traits/error_reporting/mod.rs b/compiler/rustc_infer/src/traits/error_reporting/mod.rs index b5a7d0326..9f440f398 100644 --- a/compiler/rustc_infer/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/traits/error_reporting/mod.rs @@ -25,9 +25,11 @@ impl<'tcx> InferCtxt<'tcx> { "impl has stricter requirements than trait" ); - if let Some(span) = self.tcx.hir().span_if_local(trait_item_def_id) { - let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); - err.span_label(span, format!("definition of `{}` from trait", item_name)); + if !self.tcx.is_impl_trait_in_trait(trait_item_def_id) { + if let Some(span) = self.tcx.hir().span_if_local(trait_item_def_id) { + let item_name = self.tcx.item_name(impl_item_def_id.to_def_id()); + err.span_label(span, format!("definition of `{}` from trait", item_name)); + } } err.span_label(error_span, format!("impl has extra requirement {}", requirement)); diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 8ce8b4e20..626dd9359 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -62,7 +62,8 @@ impl<'tcx, P> From> for solve::Goal<'tcx, P> { } pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; -pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; +pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>; +pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; impl<'tcx> PredicateObligation<'tcx> { /// Flips the polarity of the inner predicate. @@ -79,14 +80,14 @@ impl<'tcx> PredicateObligation<'tcx> { pub fn without_const(mut self, tcx: TyCtxt<'tcx>) -> PredicateObligation<'tcx> { self.param_env = self.param_env.without_const(); - if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = self.predicate.kind().skip_binder() && trait_pred.is_const_if_const() { - self.predicate = tcx.mk_predicate(self.predicate.kind().map_bound(|_| ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred.without_const())))); + if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) = self.predicate.kind().skip_binder() && trait_pred.is_const_if_const() { + self.predicate = tcx.mk_predicate(self.predicate.kind().map_bound(|_| ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred.without_const())))); } self } } -impl<'tcx> TraitObligation<'tcx> { +impl<'tcx> PolyTraitObligation<'tcx> { /// Returns `true` if the trait predicate is considered `const` in its ParamEnv. pub fn is_const(&self) -> bool { matches!( @@ -193,7 +194,7 @@ impl<'tcx> FulfillmentError<'tcx> { } } -impl<'tcx> TraitObligation<'tcx> { +impl<'tcx> PolyTraitObligation<'tcx> { pub fn polarity(&self) -> ty::ImplPolarity { self.predicate.skip_binder().polarity } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 74a78f380..074ff7ec9 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -3,7 +3,7 @@ use smallvec::smallvec; use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::traits::{self, Obligation, PredicateObligation}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_middle::ty::{self, ToPredicate, TyCtxt}; +use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -80,14 +80,14 @@ pub struct Elaborator<'tcx, O> { pub trait Elaboratable<'tcx> { fn predicate(&self) -> ty::Predicate<'tcx>; - // Makes a new `Self` but with a different predicate. - fn child(&self, predicate: ty::Predicate<'tcx>) -> Self; + // Makes a new `Self` but with a different clause that comes from elaboration. + fn child(&self, clause: ty::Clause<'tcx>) -> Self; - // Makes a new `Self` but with a different predicate and a different cause - // code (if `Self` has one). + // Makes a new `Self` but with a different clause and a different cause + // code (if `Self` has one, such as [`PredicateObligation`]). fn child_with_derived_cause( &self, - predicate: ty::Predicate<'tcx>, + clause: ty::Clause<'tcx>, span: Span, parent_trait_pred: ty::PolyTraitPredicate<'tcx>, index: usize, @@ -99,18 +99,18 @@ impl<'tcx> Elaboratable<'tcx> for PredicateObligation<'tcx> { self.predicate } - fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { + fn child(&self, clause: ty::Clause<'tcx>) -> Self { Obligation { cause: self.cause.clone(), param_env: self.param_env, recursion_depth: 0, - predicate, + predicate: clause.as_predicate(), } } fn child_with_derived_cause( &self, - predicate: ty::Predicate<'tcx>, + clause: ty::Clause<'tcx>, span: Span, parent_trait_pred: ty::PolyTraitPredicate<'tcx>, index: usize, @@ -123,7 +123,12 @@ impl<'tcx> Elaboratable<'tcx> for PredicateObligation<'tcx> { span, })) }); - Obligation { cause, param_env: self.param_env, recursion_depth: 0, predicate } + Obligation { + cause, + param_env: self.param_env, + recursion_depth: 0, + predicate: clause.as_predicate(), + } } } @@ -132,18 +137,18 @@ impl<'tcx> Elaboratable<'tcx> for ty::Predicate<'tcx> { *self } - fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { - predicate + fn child(&self, clause: ty::Clause<'tcx>) -> Self { + clause.as_predicate() } fn child_with_derived_cause( &self, - predicate: ty::Predicate<'tcx>, + clause: ty::Clause<'tcx>, _span: Span, _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, _index: usize, ) -> Self { - predicate + clause.as_predicate() } } @@ -152,18 +157,58 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) { self.0 } - fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { - (predicate, self.1) + fn child(&self, clause: ty::Clause<'tcx>) -> Self { + (clause.as_predicate(), self.1) + } + + fn child_with_derived_cause( + &self, + clause: ty::Clause<'tcx>, + _span: Span, + _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, + _index: usize, + ) -> Self { + (clause.as_predicate(), self.1) + } +} + +impl<'tcx> Elaboratable<'tcx> for (ty::Clause<'tcx>, Span) { + fn predicate(&self) -> ty::Predicate<'tcx> { + self.0.as_predicate() + } + + fn child(&self, clause: ty::Clause<'tcx>) -> Self { + (clause, self.1) } fn child_with_derived_cause( &self, - predicate: ty::Predicate<'tcx>, + clause: ty::Clause<'tcx>, _span: Span, _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, _index: usize, ) -> Self { - (predicate, self.1) + (clause, self.1) + } +} + +impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> { + fn predicate(&self) -> ty::Predicate<'tcx> { + self.as_predicate() + } + + fn child(&self, clause: ty::Clause<'tcx>) -> Self { + clause + } + + fn child_with_derived_cause( + &self, + clause: ty::Clause<'tcx>, + _span: Span, + _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, + _index: usize, + ) -> Self { + clause } } @@ -199,7 +244,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { let bound_predicate = elaboratable.predicate().kind(); match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::Clause::Trait(data)) => { + ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => { // Negative trait bounds do not imply any supertrait bounds if data.polarity == ty::ImplPolarity::Negative { return; @@ -212,13 +257,13 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { }; let obligations = - predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| { + predicates.predicates.iter().enumerate().map(|(index, &(mut clause, span))| { // when parent predicate is non-const, elaborate it to non-const predicates. if data.constness == ty::BoundConstness::NotConst { - pred = pred.without_const(tcx); + clause = clause.without_const(tcx); } elaboratable.child_with_derived_cause( - pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), + clause.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), span, bound_predicate.rebind(data), index, @@ -227,7 +272,7 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { debug!(?data, ?obligations, "super_predicates"); self.extend_deduped(obligations); } - ty::PredicateKind::WellFormed(..) => { + ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..)) => { // Currently, we do not elaborate WF predicates, // although we easily could. } @@ -243,13 +288,13 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { // Currently, we do not "elaborate" predicates like `X -> Y`, // though conceivably we might. } - ty::PredicateKind::Clause(ty::Clause::Projection(..)) => { + ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => { // Nothing to elaborate in a projection predicate. } ty::PredicateKind::ClosureKind(..) => { // Nothing to elaborate when waiting for a closure's kind to be inferred. } - ty::PredicateKind::ConstEvaluatable(..) => { + ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => { // Currently, we do not elaborate const-evaluatable // predicates. } @@ -257,10 +302,10 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { // Currently, we do not elaborate const-equate // predicates. } - ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..)) => { + ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => { // Nothing to elaborate from `'a: 'b`. } - ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate( + ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( ty_max, r_min, ))) => { @@ -292,17 +337,15 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { if r.is_late_bound() { None } else { - Some(ty::PredicateKind::Clause(ty::Clause::RegionOutlives( - ty::OutlivesPredicate(r, r_min), + Some(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( + r, r_min, ))) } } Component::Param(p) => { - let ty = tcx.mk_ty_param(p.index, p.name); - Some(ty::PredicateKind::Clause(ty::Clause::TypeOutlives( - ty::OutlivesPredicate(ty, r_min), - ))) + let ty = Ty::new_param(tcx, p.index, p.name); + Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min))) } Component::UnresolvedInferenceVariable(_) => None, @@ -310,8 +353,9 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { Component::Alias(alias_ty) => { // We might end up here if we have `Foo<::Assoc>: 'a`. // With this, we can deduce that `::Assoc: 'a`. - Some(ty::PredicateKind::Clause(ty::Clause::TypeOutlives( - ty::OutlivesPredicate(alias_ty.to_ty(tcx), r_min), + Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( + alias_ty.to_ty(tcx), + r_min, ))) } @@ -321,20 +365,16 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { None } }) - .map(|predicate_kind| { - bound_predicate.rebind(predicate_kind).to_predicate(tcx) - }) - .map(|predicate| elaboratable.child(predicate)), + .map(|clause| { + elaboratable.child(bound_predicate.rebind(clause).to_predicate(tcx)) + }), ); } - ty::PredicateKind::TypeWellFormedFromEnv(..) => { - // Nothing to elaborate - } ty::PredicateKind::Ambiguous => {} ty::PredicateKind::AliasRelate(..) => { // No } - ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => { + ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => { // Nothing to elaborate } } @@ -400,7 +440,7 @@ pub fn transitive_bounds_that_define_assoc_item<'tcx>( tcx.super_predicates_that_define_assoc_item((trait_ref.def_id(), assoc_name)); for (super_predicate, _) in super_predicates.predicates { let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref); - if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() { + if let Some(binder) = subst_predicate.as_trait_clause() { stack.push(binder.map_bound(|t| t.trait_ref)); } } -- cgit v1.2.3