diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 9e0aa57b2553f..8f1ae594a9247 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -489,12 +489,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // but the type has region variables, so erase those. tcx.infer_ctxt() .build() - .type_implements_trait( - default_trait, - tcx.erase_regions(ty), - ty::List::empty(), - param_env, - ) + .type_implements_trait(default_trait, [tcx.erase_regions(ty)], param_env) .must_apply_modulo_regions() }; @@ -1707,7 +1702,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_label(borrow_span, note); let tcx = self.infcx.tcx; - let ty_params = ty::List::empty(); let return_ty = self.regioncx.universal_regions().unnormalized_output_ty; let return_ty = tcx.erase_regions(return_ty); @@ -1716,7 +1710,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) && self .infcx - .type_implements_trait(iter_trait, return_ty, ty_params, self.param_env) + .type_implements_trait(iter_trait, [return_ty], self.param_env) .must_apply_modulo_regions() { err.span_suggestion_hidden( diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 9b6c7d27c791b..7467212bed883 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -547,10 +547,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { let tcx = self.tcx(); - let trait_ref = ty::TraitRef { - def_id: tcx.require_lang_item(LangItem::Copy, Some(self.last_span)), - substs: tcx.mk_substs_trait(place_ty.ty, &[]), - }; + let trait_ref = tcx.at(self.last_span).mk_trait_ref(LangItem::Copy, [place_ty.ty]); // To have a `Copy` operand, the type `T` of the // value must be `Copy`. Note that we prove that `T: Copy`, @@ -1273,10 +1270,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.check_rvalue(body, rv, location); if !self.unsized_feature_enabled() { - let trait_ref = ty::TraitRef { - def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)), - substs: tcx.mk_substs_trait(place_ty, &[]), - }; + let trait_ref = + tcx.at(self.last_span).mk_trait_ref(LangItem::Sized, [place_ty]); self.prove_trait_ref( trait_ref, location.to_locations(), @@ -1840,6 +1835,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { #[instrument(skip(self, body), level = "debug")] fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) { let tcx = self.tcx(); + let span = body.source_info(location).span; match rvalue { Rvalue::Aggregate(ak, ops) => { @@ -1863,12 +1859,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } Operand::Move(place) => { // Make sure that repeated elements implement `Copy`. - let span = body.source_info(location).span; let ty = place.ty(body, tcx).ty; - let trait_ref = ty::TraitRef::new( - tcx.require_lang_item(LangItem::Copy, Some(span)), - tcx.mk_substs_trait(ty, &[]), - ); + let trait_ref = tcx.at(span).mk_trait_ref(LangItem::Copy, [ty]); self.prove_trait_ref( trait_ref, @@ -1881,10 +1873,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } &Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => { - let trait_ref = ty::TraitRef { - def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)), - substs: tcx.mk_substs_trait(ty, &[]), - }; + let trait_ref = tcx.at(span).mk_trait_ref(LangItem::Sized, [ty]); self.prove_trait_ref( trait_ref, @@ -1896,10 +1885,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Rvalue::ShallowInitBox(operand, ty) => { self.check_operand(operand, location); - let trait_ref = ty::TraitRef { - def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)), - substs: tcx.mk_substs_trait(*ty, &[]), - }; + let trait_ref = tcx.at(span).mk_trait_ref(LangItem::Sized, [*ty]); self.prove_trait_ref( trait_ref, @@ -1996,11 +1982,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { CastKind::Pointer(PointerCast::Unsize) => { let &ty = ty; - let trait_ref = ty::TraitRef { - def_id: tcx - .require_lang_item(LangItem::CoerceUnsized, Some(self.last_span)), - substs: tcx.mk_substs_trait(op.ty(body, tcx), &[ty.into()]), - }; + let trait_ref = tcx + .at(span) + .mk_trait_ref(LangItem::CoerceUnsized, [op.ty(body, tcx), ty]); self.prove_trait_ref( trait_ref, diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index 6fd12985170e6..e7b3df9b7288b 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -153,17 +153,12 @@ impl Qualif for NeedsNonConstDrop { return false; } - let destruct = cx.tcx.require_lang_item(LangItem::Destruct, None); - let obligation = Obligation::new( cx.tcx, - ObligationCause::dummy(), + ObligationCause::dummy_with_span(cx.body.span), cx.param_env, ty::Binder::dummy(ty::TraitPredicate { - trait_ref: ty::TraitRef { - def_id: destruct, - substs: cx.tcx.mk_substs_trait(ty, &[]), - }, + trait_ref: cx.tcx.at(cx.body.span).mk_trait_ref(LangItem::Destruct, [ty]), constness: ty::BoundConstness::ConstIfConst, polarity: ty::ImplPolarity::Positive, }), diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index 6a28bb16a20ac..3e3544ce666e3 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -60,13 +60,10 @@ impl<'tcx> Bounds<'tcx> { { // If it could be sized, and is, add the `Sized` predicate. let sized_predicate = self.implicitly_sized.and_then(|span| { - tcx.lang_items().sized_trait().map(move |sized| { - let trait_ref = ty::Binder::dummy(ty::TraitRef { - def_id: sized, - substs: tcx.mk_substs_trait(param_ty, &[]), - }); - (trait_ref.without_const().to_predicate(tcx), span) - }) + // FIXME: use tcx.at(span).mk_trait_ref(LangItem::Sized) here? This may make no-core code harder to write. + let sized = tcx.lang_items().sized_trait()?; + let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(sized, [param_ty])); + Some((trait_ref.without_const().to_predicate(tcx), span)) }); let region_preds = self.region_bounds.iter().map(move |&(region_bound, span)| { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index b81f9d7a6d2c1..7119f3a238697 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1722,7 +1722,7 @@ fn receiver_is_valid<'tcx>( // The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it. autoderef.next(); - let receiver_trait_def_id = tcx.require_lang_item(LangItem::Receiver, None); + let receiver_trait_def_id = tcx.require_lang_item(LangItem::Receiver, Some(span)); // Keep dereferencing `receiver_ty` until we get to `self_ty`. loop { @@ -1782,10 +1782,7 @@ fn receiver_is_implemented<'tcx>( receiver_ty: Ty<'tcx>, ) -> bool { let tcx = wfcx.tcx(); - let trait_ref = ty::Binder::dummy(ty::TraitRef { - def_id: receiver_trait_def_id, - substs: tcx.mk_substs_trait(receiver_ty, &[]), - }); + let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(receiver_trait_def_id, [receiver_ty])); let obligation = traits::Obligation::new(tcx, cause, wfcx.param_env, trait_ref.without_const()); diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 6f74ef3ccad6d..b2c9e7389b047 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -315,8 +315,7 @@ fn visit_implementation_of_dispatch_from_dyn<'tcx>(tcx: TyCtxt<'tcx>, impl_did: cause.clone(), dispatch_from_dyn_trait, 0, - field.ty(tcx, substs_a), - &[field.ty(tcx, substs_b).into()], + [field.ty(tcx, substs_a), field.ty(tcx, substs_b)], ) }), ); @@ -558,7 +557,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn // Register an obligation for `A: Trait`. let cause = traits::ObligationCause::misc(span, impl_hir_id); let predicate = - predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, source, &[target.into()]); + predicate_for_trait_def(tcx, param_env, cause, trait_def_id, 0, [source, target]); let errors = traits::fully_solve_obligation(&infcx, predicate); if !errors.is_empty() { infcx.err_ctxt().report_fulfillment_errors(&errors, None); diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 139f2e8413662..31432bb6e4170 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -539,17 +539,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .subst_iter_copied(self.tcx, substs) { let pred = pred.kind().rebind(match pred.kind().skip_binder() { - ty::PredicateKind::Trait(mut trait_pred) => { + ty::PredicateKind::Trait(trait_pred) => { assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty); - trait_pred.trait_ref.substs = - self.tcx.mk_substs_trait(ty, &trait_pred.trait_ref.substs[1..]); - ty::PredicateKind::Trait(trait_pred) + ty::PredicateKind::Trait(trait_pred.with_self_type(self.tcx, ty)) } ty::PredicateKind::Projection(mut proj_pred) => { assert_eq!(proj_pred.projection_ty.self_ty(), opaque_ty); - proj_pred.projection_ty.substs = self - .tcx - .mk_substs_trait(ty, &proj_pred.projection_ty.substs[1..]); + proj_pred.projection_ty.substs = self.tcx.mk_substs_trait( + ty, + proj_pred.projection_ty.substs.iter().skip(1), + ); ty::PredicateKind::Projection(proj_pred) } _ => continue, diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index e5dc4b06c0ba6..5e1e44dcb6d15 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -498,10 +498,9 @@ impl<'a, 'tcx> CastCheck<'tcx> { let ty = fcx.tcx.erase_regions(ty); let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty); let expr_ty = fcx.tcx.erase_regions(expr_ty); - let ty_params = fcx.tcx.mk_substs_trait(expr_ty, &[]); if fcx .infcx - .type_implements_trait(from_trait, ty, ty_params, fcx.param_env) + .type_implements_trait(from_trait, [ty, expr_ty], fcx.param_env) .must_apply_modulo_regions() { label = false; diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index cf3b37f0a2508..43c7127b0d4c5 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -630,8 +630,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { cause, coerce_unsized_did, 0, - coerce_source, - &[coerce_target.into()] + [coerce_source, coerce_target] )]; let mut has_unsized_tuple_coercion = false; @@ -805,10 +804,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { self.tcx, self.cause.clone(), self.param_env, - ty::Binder::dummy(ty::TraitRef::new( - self.tcx.require_lang_item(hir::LangItem::PointerSized, Some(self.cause.span)), - self.tcx.mk_substs_trait(a, &[]), - )) + ty::Binder::dummy( + self.tcx.at(self.cause.span).mk_trait_ref(hir::LangItem::PointerSized, [a]), + ) .to_poly_trait_predicate(), )); } @@ -1086,8 +1084,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.infcx .type_implements_trait( self.tcx.lang_items().deref_mut_trait()?, - expr_ty, - ty::List::empty(), + [expr_ty], self.param_env, ) .may_apply() diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 2764de751b08b..de30bfe6923a7 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1119,8 +1119,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .infcx .type_implements_trait( self.tcx.lang_items().sized_trait().unwrap(), - lhs_deref_ty, - ty::List::empty(), + [lhs_deref_ty], self.param_env, ) .may_apply(); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 9f5aadca967bd..b5aa8cd6e7c5b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1093,10 +1093,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx, self.misc(expr.span), self.param_env, - ty::Binder::dummy(ty::TraitRef { - def_id: into_def_id, - substs: self.tcx.mk_substs_trait(expr_ty, &[expected_ty.into()]), - }) + ty::Binder::dummy(self.tcx.mk_trait_ref( + into_def_id, + [expr_ty, expected_ty] + )) .to_poly_trait_predicate(), )) { diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs index 3c98a2aa3aba3..89746ce54a643 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs @@ -8,7 +8,7 @@ use hir::ItemKind; use rustc_ast::Mutability; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_middle::ty::subst::InternalSubsts; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_middle::ty::{Adt, Array, Ref, Ty}; use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS; use rustc_span::symbol::kw::{Empty, Underscore}; @@ -227,14 +227,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If we know it does not, we don't need to warn. if method_name.name == sym::from_iter { if let Some(trait_def_id) = self.tcx.get_diagnostic_item(sym::FromIterator) { + let any_type = self.infcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span, + }); if !self .infcx - .type_implements_trait( - trait_def_id, - self_ty, - InternalSubsts::empty(), - self.param_env, - ) + .type_implements_trait(trait_def_id, [self_ty, any_type], self.param_env) .may_apply() { return; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8190163cba15b..d0ea2b0e66475 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -68,16 +68,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.autoderef(span, ty).any(|(ty, _)| { info!("check deref {:?} impl FnOnce", ty); self.probe(|_| { - let fn_once_substs = tcx.mk_substs_trait( - ty, - &[self - .next_ty_var(TypeVariableOrigin { + let trait_ref = tcx.mk_trait_ref( + fn_once, + [ + ty, + self.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span, - }) - .into()], + }), + ], ); - let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs); let poly_trait_ref = ty::Binder::dummy(trait_ref); let obligation = Obligation::misc( tcx, diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 4dea40829f622..68f119adc7a7c 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -970,12 +970,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { check_trait .map(|check_trait| { self.infcx - .type_implements_trait( - check_trait, - ty, - self.tcx.mk_substs_trait(ty, &[]), - self.param_env, - ) + .type_implements_trait(check_trait, [ty], self.param_env) .must_apply_modulo_regions() }) .unwrap_or(false), @@ -999,12 +994,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { check_trait .map(|check_trait| { self.infcx - .type_implements_trait( - check_trait, - ty, - self.tcx.mk_substs_trait(ty, &[]), - self.param_env, - ) + .type_implements_trait(check_trait, [ty], self.param_env) .must_apply_modulo_regions() }) .unwrap_or(false), @@ -1347,14 +1337,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_drop_defined_for_ty = |ty: Ty<'tcx>| { let drop_trait = self.tcx.require_lang_item(hir::LangItem::Drop, Some(closure_span)); - let ty_params = self.tcx.mk_substs_trait(base_path_ty, &[]); self.infcx - .type_implements_trait( - drop_trait, - ty, - ty_params, - self.tcx.param_env(closure_def_id), - ) + .type_implements_trait(drop_trait, [ty], self.tcx.param_env(closure_def_id)) .must_apply_modulo_regions() }; diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index b2b985a22ac01..54224c9b5de22 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -27,7 +27,7 @@ pub trait TraitEngine<'tcx>: 'tcx { def_id: DefId, cause: ObligationCause<'tcx>, ) { - let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) }; + let trait_ref = infcx.tcx.mk_trait_ref(def_id, [ty]); self.register_predicate_obligation( infcx, Obligation { diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 83e6f4e33bed8..c1820ac4d1eab 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -5,7 +5,6 @@ use rustc_hir as hir; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::lint::in_external_macro; use rustc_middle::ty; -use rustc_middle::ty::subst::InternalSubsts; use rustc_parse_format::{ParseMode, Parser, Piece}; use rustc_session::lint::FutureIncompatibilityReason; use rustc_span::edition::Edition; @@ -153,17 +152,17 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc let infcx = cx.tcx.infer_ctxt().build(); let suggest_display = is_str - || cx.tcx.get_diagnostic_item(sym::Display).map(|t| { - infcx - .type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env) - .may_apply() - }) == Some(true); + || cx + .tcx + .get_diagnostic_item(sym::Display) + .map(|t| infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()) + == Some(true); let suggest_debug = !suggest_display - && cx.tcx.get_diagnostic_item(sym::Debug).map(|t| { - infcx - .type_implements_trait(t, ty, InternalSubsts::empty(), cx.param_env) - .may_apply() - }) == Some(true); + && cx + .tcx + .get_diagnostic_item(sym::Debug) + .map(|t| infcx.type_implements_trait(t, [ty], cx.param_env).may_apply()) + == Some(true); let suggest_panic_any = !is_str && panic == sym::std_panic_macro; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e0a786e201a16..8b70eabb105c8 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1884,7 +1884,7 @@ impl<'tcx> Operand<'tcx> { substs: SubstsRef<'tcx>, span: Span, ) -> Self { - let ty = tcx.bound_type_of(def_id).subst(tcx, substs); + let ty = tcx.mk_fn_def(def_id, substs); Operand::Constant(Box::new(Constant { span, user_ty: None, diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index 4682ac96b5297..b8e6f0258d019 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -1,7 +1,5 @@ -use crate::ty::subst::SubstsRef; use crate::ty::{self, Ty, TyCtxt}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_macros::HashStable; use rustc_span::Span; @@ -121,7 +119,8 @@ pub struct OverloadedDeref<'tcx> { } impl<'tcx> OverloadedDeref<'tcx> { - pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> (DefId, SubstsRef<'tcx>) { + /// Get the zst function item type for this method call. + pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> Ty<'tcx> { let trait_def_id = match self.mutbl { hir::Mutability::Not => tcx.require_lang_item(LangItem::Deref, None), hir::Mutability::Mut => tcx.require_lang_item(LangItem::DerefMut, None), @@ -132,7 +131,7 @@ impl<'tcx> OverloadedDeref<'tcx> { .find(|m| m.kind == ty::AssocKind::Fn) .unwrap() .def_id; - (method_def_id, tcx.mk_substs_trait(source, &[])) + tcx.mk_fn_def(method_def_id, tcx.mk_substs_trait(source, [])) } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 13695089eb828..8d6ae14231457 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2516,7 +2516,7 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_ty(Tuple(self.intern_type_list(&ts))) } - pub fn mk_tup], Ty<'tcx>>>(self, iter: I) -> I::Output { + pub fn mk_tup, Ty<'tcx>>>(self, iter: I) -> I::Output { iter.intern_with(|ts| self.mk_ty(Tuple(self.intern_type_list(&ts)))) } @@ -2532,6 +2532,11 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_fn_def(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { + debug_assert_eq!( + self.generics_of(def_id).count(), + substs.len(), + "wrong number of generic parameters for {def_id:?}: {substs:?}", + ); self.mk_ty(FnDef(def_id, substs)) } @@ -2552,6 +2557,11 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_projection(self, item_def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> { + debug_assert_eq!( + self.generics_of(item_def_id).count(), + substs.len(), + "wrong number of generic parameters for {item_def_id:?}: {substs:?}", + ); self.mk_ty(Projection(ProjectionTy { item_def_id, substs })) } @@ -2766,7 +2776,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn mk_poly_existential_predicates< - I: InternAs<[PolyExistentialPredicate<'tcx>], &'tcx List>>, + I: InternAs, &'tcx List>>, >( self, iter: I, @@ -2774,37 +2784,58 @@ impl<'tcx> TyCtxt<'tcx> { iter.intern_with(|xs| self.intern_poly_existential_predicates(xs)) } - pub fn mk_predicates], &'tcx List>>>( + pub fn mk_predicates, &'tcx List>>>( self, iter: I, ) -> I::Output { iter.intern_with(|xs| self.intern_predicates(xs)) } - pub fn mk_type_list], &'tcx List>>>(self, iter: I) -> I::Output { + pub fn mk_type_list, &'tcx List>>>(self, iter: I) -> I::Output { iter.intern_with(|xs| self.intern_type_list(xs)) } - pub fn mk_substs], &'tcx List>>>( + pub fn mk_substs, &'tcx List>>>( self, iter: I, ) -> I::Output { iter.intern_with(|xs| self.intern_substs(xs)) } - pub fn mk_place_elems], &'tcx List>>>( + pub fn mk_place_elems, &'tcx List>>>( self, iter: I, ) -> I::Output { iter.intern_with(|xs| self.intern_place_elems(xs)) } - pub fn mk_substs_trait(self, self_ty: Ty<'tcx>, rest: &[GenericArg<'tcx>]) -> SubstsRef<'tcx> { - self.mk_substs(iter::once(self_ty.into()).chain(rest.iter().cloned())) + pub fn mk_substs_trait( + self, + self_ty: Ty<'tcx>, + rest: impl IntoIterator>, + ) -> SubstsRef<'tcx> { + self.mk_substs(iter::once(self_ty.into()).chain(rest)) + } + + pub fn mk_trait_ref( + self, + trait_def_id: DefId, + substs: impl IntoIterator>>, + ) -> ty::TraitRef<'tcx> { + let substs = substs.into_iter().map(Into::into); + let n = self.generics_of(trait_def_id).count(); + debug_assert_eq!( + (n, Some(n)), + substs.size_hint(), + "wrong number of generic parameters for {trait_def_id:?}: {:?} \nDid you accidentally include the self-type in the params list?", + substs.collect::>(), + ); + let substs = self.mk_substs(substs); + ty::TraitRef::new(trait_def_id, substs) } pub fn mk_bound_variable_kinds< - I: InternAs<[ty::BoundVariableKind], &'tcx List>, + I: InternAs>, >( self, iter: I, @@ -2959,6 +2990,15 @@ impl<'tcx> TyCtxtAt<'tcx> { pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> { self.tcx.ty_error_with_message(self.span, msg) } + + pub fn mk_trait_ref( + self, + trait_lang_item: LangItem, + substs: impl IntoIterator>>, + ) -> ty::TraitRef<'tcx> { + let trait_def_id = self.require_lang_item(trait_lang_item, Some(self.span)); + self.tcx.mk_trait_ref(trait_def_id, substs) + } } /// Parameter attributes that can only be determined by examining the body of a function instead diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index a792d2694b3b9..586460986dd73 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -551,7 +551,7 @@ impl<'tcx> Instance<'tcx> { let sig = tcx.try_normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig).ok()?; assert_eq!(sig.inputs().len(), 1); - let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]); + let substs = tcx.mk_substs_trait(self_ty, [sig.inputs()[0].into()]); debug!(?self_ty, ?sig); Some(Instance { def, substs }) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index b4779655252f9..8bac76d559f24 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -852,6 +852,10 @@ impl<'tcx> TraitPredicate<'tcx> { } } + pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + Self { trait_ref: self.trait_ref.with_self_type(tcx, self_ty), ..self } + } + pub fn def_id(self) -> DefId { self.trait_ref.def_id } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index e2a7b09de6ab4..db18558e947a3 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -719,10 +719,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx) } ExistentialPredicate::AutoTrait(did) => { - let trait_ref = self.rebind(ty::TraitRef { - def_id: did, - substs: tcx.mk_substs_trait(self_ty, &[]), - }); + let trait_ref = self.rebind(tcx.mk_trait_ref(did, [self_ty])); trait_ref.without_const().to_predicate(tcx) } } @@ -814,6 +811,13 @@ impl<'tcx> TraitRef<'tcx> { TraitRef { def_id, substs } } + pub fn with_self_type(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + tcx.mk_trait_ref( + self.def_id, + [self_ty.into()].into_iter().chain(self.substs.iter().skip(1)), + ) + } + /// Returns a `TraitRef` of the form `P0: Foo` where `Pi` /// are the parameters defined on trait. pub fn identity(tcx: TyCtxt<'tcx>, def_id: DefId) -> Binder<'tcx, TraitRef<'tcx>> { @@ -909,7 +913,7 @@ impl<'tcx> ExistentialTraitRef<'tcx> { // otherwise the escaping vars would be captured by the binder // debug_assert!(!self_ty.has_escaping_bound_vars()); - ty::TraitRef { def_id: self.def_id, substs: tcx.mk_substs_trait(self_ty, self.substs) } + tcx.mk_trait_ref(self.def_id, [self_ty.into()].into_iter().chain(self.substs.iter())) } } diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index af0d7879c576a..a62cfecf78b78 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -250,7 +250,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let ref_str_ty = tcx.mk_imm_ref(re_erased, tcx.types.str_); let ref_str = self.temp(ref_str_ty, test.span); let deref = tcx.require_lang_item(LangItem::Deref, None); - let method = trait_method(tcx, deref, sym::deref, ty, &[]); + let method = trait_method(tcx, deref, sym::deref, [ty]); let eq_block = self.cfg.start_new_block(); self.cfg.push_assign(block, source_info, ref_string, Rvalue::Ref(re_erased, BorrowKind::Shared, place)); self.cfg.terminate( @@ -444,8 +444,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { bug!("non_scalar_compare called on non-reference type: {}", ty); }; - let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, None); - let method = trait_method(self.tcx, eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]); + let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, Some(source_info.span)); + let method = trait_method(self.tcx, eq_def_id, sym::eq, [deref_ty, deref_ty]); let bool_ty = self.tcx.types.bool; let eq_result = self.temp(bool_ty, source_info.span); @@ -837,10 +837,9 @@ fn trait_method<'tcx>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, method_name: Symbol, - self_ty: Ty<'tcx>, - params: &[GenericArg<'tcx>], + substs: impl IntoIterator>>, ) -> ConstantKind<'tcx> { - let substs = tcx.mk_substs_trait(self_ty, params); + let substs = tcx.mk_substs(substs.into_iter().map(Into::into)); // The unhygienic comparison here is acceptable because this is only // used on known traits. @@ -850,8 +849,7 @@ fn trait_method<'tcx>( .find(|item| item.kind == ty::AssocKind::Fn) .expect("trait method not found"); - let method_ty = tcx.bound_type_of(item.def_id); - let method_ty = method_ty.subst(tcx, substs); + let method_ty = tcx.mk_fn_def(item.def_id, substs); ConstantKind::zero_sized(method_ty) } diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index b53bd3d0710a6..8797529459534 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -3,6 +3,7 @@ //! This crate also contains the match exhaustiveness and usefulness checking. #![allow(rustc::potential_query_instability)] #![feature(assert_matches)] +#![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(if_let_guard)] diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 57382f5e1bdb2..60e64b45963c3 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -14,11 +14,10 @@ use rustc_middle::thir::*; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCast, }; -use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; +use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{ self, AdtKind, InlineConstSubsts, InlineConstSubstsParts, ScalarInt, Ty, UpvarSubsts, UserType, }; -use rustc_span::def_id::DefId; use rustc_span::Span; use rustc_target::abi::VariantIdx; @@ -806,12 +805,12 @@ impl<'tcx> Cx<'tcx> { &mut self, expr: &hir::Expr<'_>, span: Span, - overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, + overloaded_callee: Option>, ) -> Expr<'tcx> { let temp_lifetime = self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id); - let (def_id, substs, user_ty) = match overloaded_callee { - Some((def_id, substs)) => (def_id, substs, None), + let (ty, user_ty) = match overloaded_callee { + Some(fn_def) => (fn_def, None), None => { let (kind, def_id) = self.typeck_results().type_dependent_def(expr.hir_id).unwrap_or_else(|| { @@ -819,10 +818,12 @@ impl<'tcx> Cx<'tcx> { }); let user_ty = self.user_substs_applied_to_res(expr.hir_id, Res::Def(kind, def_id)); debug!("method_callee: user_ty={:?}", user_ty); - (def_id, self.typeck_results().node_substs(expr.hir_id), user_ty) + ( + self.tcx().mk_fn_def(def_id, self.typeck_results().node_substs(expr.hir_id)), + user_ty, + ) } }; - let ty = self.tcx().mk_fn_def(def_id, substs); Expr { temp_lifetime, ty, span, kind: ExprKind::ZstLiteral { user_ty } } } @@ -957,7 +958,7 @@ impl<'tcx> Cx<'tcx> { &mut self, expr: &'tcx hir::Expr<'tcx>, place_ty: Ty<'tcx>, - overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, + overloaded_callee: Option>, args: Box<[ExprId]>, span: Span, ) -> ExprKind<'tcx> { diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index ad12e01162117..a21f6cd39f014 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -232,8 +232,7 @@ impl<'tcx> ConstToPat<'tcx> { ObligationCause::misc(self.span, self.id), partial_eq_trait_id, 0, - ty, - &[], + [ty, ty], ); // FIXME: should this call a `predicate_must_hold` variant instead? diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs index 14d265a402ef8..ce87a1916b465 100644 --- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs +++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs @@ -615,7 +615,7 @@ where let drop_trait = tcx.require_lang_item(LangItem::Drop, None); let drop_fn = tcx.associated_item_def_ids(drop_trait)[0]; let ty = self.place_ty(self.place); - let substs = tcx.mk_substs_trait(ty, &[]); + let substs = tcx.mk_substs_trait(ty, []); let ref_ty = tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty, mutbl: hir::Mutability::Mut }); diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index a0ff7550faeb8..68703eb0a232e 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -346,7 +346,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { // we must subst the self_ty because it's // otherwise going to be TySelf and we can't index // or access fields of a Place of type TySelf. - let substs = tcx.mk_substs_trait(self_ty, &[]); + let substs = tcx.mk_substs_trait(self_ty, []); let sig = tcx.bound_fn_sig(def_id).subst(tcx, substs); let sig = tcx.erase_late_bound_regions(sig); let span = tcx.def_span(def_id); @@ -427,7 +427,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { ) { let tcx = self.tcx; - let substs = tcx.mk_substs_trait(ty, &[]); + let substs = tcx.mk_substs_trait(ty, []); // `func == Clone::clone(&ty) -> ty` let func_ty = tcx.mk_fn_def(self.def_id, substs); @@ -586,7 +586,7 @@ fn build_call_shim<'tcx>( // Create substitutions for the `Self` and `Args` generic parameters of the shim body. let arg_tup = tcx.mk_tup(untuple_args.iter()); - let sig_substs = tcx.mk_substs_trait(ty, &[ty::subst::GenericArg::from(arg_tup)]); + let sig_substs = tcx.mk_substs_trait(ty, [ty::subst::GenericArg::from(arg_tup)]); (Some(sig_substs), Some(untuple_args)) } else { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index d74893bf0f0e3..559ce227454de 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -187,6 +187,7 @@ use rustc_middle::mir::visit::Visitor as MirVisitor; use rustc_middle::mir::{self, Local, Location}; use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc_middle::ty::print::with_no_trimmed_paths; +use rustc_middle::ty::query::TyCtxtAt; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::{ self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitable, VtblEntry, @@ -688,7 +689,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { let source_ty = operand.ty(self.body, self.tcx); let source_ty = self.monomorphize(source_ty); let (source_ty, target_ty) = - find_vtable_types_for_unsizing(self.tcx, source_ty, target_ty); + find_vtable_types_for_unsizing(self.tcx.at(span), source_ty, target_ty); // This could also be a different Unsize instruction, like // from a fixed sized array to a slice. But we are only // interested in things that produce a vtable. @@ -1053,14 +1054,14 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) -> /// Finally, there is also the case of custom unsizing coercions, e.g., for /// smart pointers such as `Rc` and `Arc`. fn find_vtable_types_for_unsizing<'tcx>( - tcx: TyCtxt<'tcx>, + tcx: TyCtxtAt<'tcx>, source_ty: Ty<'tcx>, target_ty: Ty<'tcx>, ) -> (Ty<'tcx>, Ty<'tcx>) { let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| { let param_env = ty::ParamEnv::reveal_all(); let type_has_metadata = |ty: Ty<'tcx>| -> bool { - if ty.is_sized(tcx, param_env) { + if ty.is_sized(tcx.tcx, param_env) { return false; } let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env); @@ -1104,8 +1105,8 @@ fn find_vtable_types_for_unsizing<'tcx>( find_vtable_types_for_unsizing( tcx, - source_fields[coerce_index].ty(tcx, source_substs), - target_fields[coerce_index].ty(tcx, target_substs), + source_fields[coerce_index].ty(*tcx, source_substs), + target_fields[coerce_index].ty(*tcx, target_substs), ) } _ => bug!( diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 42781bd25f05b..b616ed35d99d7 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -13,8 +13,8 @@ extern crate rustc_middle; use rustc_hir::lang_items::LangItem; use rustc_middle::traits; use rustc_middle::ty::adjustment::CustomCoerceUnsized; -use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::ty::query::{Providers, TyCtxtAt}; +use rustc_middle::ty::{self, Ty}; mod collector; mod errors; @@ -23,16 +23,12 @@ mod polymorphize; mod util; fn custom_coerce_unsize_info<'tcx>( - tcx: TyCtxt<'tcx>, + tcx: TyCtxtAt<'tcx>, source_ty: Ty<'tcx>, target_ty: Ty<'tcx>, ) -> CustomCoerceUnsized { - let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None); - - let trait_ref = ty::Binder::dummy(ty::TraitRef { - def_id, - substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]), - }); + let trait_ref = + ty::Binder::dummy(tcx.mk_trait_ref(LangItem::CoerceUnsized, [source_ty, target_ty])); match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) { Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData { diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index b7240a8289730..9b39a9401149a 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -4,7 +4,7 @@ use crate::traits::{self, TraitEngine, TraitEngineExt}; use rustc_hir as hir; use rustc_infer::infer::InferCtxt; use rustc_middle::ty::TypeVisitable; -use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::Span; @@ -122,10 +122,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { let tcx = self.infcx.tcx; // - let trait_ref = TraitRef { - def_id: tcx.lang_items().deref_trait()?, - substs: tcx.mk_substs_trait(ty, &[]), - }; + let trait_ref = tcx.mk_trait_ref(tcx.lang_items().deref_trait()?, [ty]); let cause = traits::ObligationCause::misc(self.span, self.body_id); diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 0f2e22604dc7e..25a9c29caa7ab 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -7,9 +7,8 @@ use rustc_infer::traits::ObligationCause; use rustc_middle::arena::ArenaAllocatable; use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse}; use rustc_middle::traits::query::Fallible; -use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::ToPredicate; use rustc_middle::ty::{self, Ty, TypeFoldable, TypeVisitable}; +use rustc_middle::ty::{GenericArg, ToPredicate}; use rustc_span::{Span, DUMMY_SP}; use std::fmt::Debug; @@ -44,8 +43,7 @@ pub trait InferCtxtExt<'tcx> { /// The inputs are: /// /// - the def-id of the trait - /// - the self type - /// - the *other* type parameters of the trait, excluding the self-type + /// - the type parameters of the trait, including the self-type /// - the parameter environment /// /// Invokes `evaluate_obligation`, so in the event that evaluating @@ -54,8 +52,7 @@ pub trait InferCtxtExt<'tcx> { fn type_implements_trait( &self, trait_def_id: DefId, - ty: Ty<'tcx>, - params: SubstsRef<'tcx>, + params: impl IntoIterator>>, param_env: ty::ParamEnv<'tcx>, ) -> traits::EvaluationResult; } @@ -109,16 +106,14 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { InferOk { value, obligations } } - #[instrument(level = "debug", skip(self), ret)] + #[instrument(level = "debug", skip(self, params), ret)] fn type_implements_trait( &self, trait_def_id: DefId, - ty: Ty<'tcx>, - params: SubstsRef<'tcx>, + params: impl IntoIterator>>, param_env: ty::ParamEnv<'tcx>, ) -> traits::EvaluationResult { - let trait_ref = - ty::TraitRef { def_id: trait_def_id, substs: self.tcx.mk_substs_trait(ty, params) }; + let trait_ref = self.tcx.mk_trait_ref(trait_def_id, params); let obligation = traits::Obligation { cause: traits::ObligationCause::dummy(), diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 2dce18e2d3cad..975ff31a60788 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -11,6 +11,7 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(associated_type_bounds)] #![feature(box_patterns)] #![feature(control_flow_enum)] #![feature(drain_filter)] diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 5869bc76b596c..a057e45ad6af4 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -86,7 +86,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { ) -> AutoTraitResult { let tcx = self.tcx; - let trait_ref = ty::TraitRef { def_id: trait_did, substs: tcx.mk_substs_trait(ty, &[]) }; + let trait_ref = tcx.mk_trait_ref(trait_did, [ty]); let trait_pred = ty::Binder::dummy(trait_ref); @@ -260,10 +260,8 @@ impl<'tcx> AutoTraitFinder<'tcx> { let mut already_visited = FxHashSet::default(); let mut predicates = VecDeque::new(); predicates.push_back(ty::Binder::dummy(ty::TraitPredicate { - trait_ref: ty::TraitRef { - def_id: trait_did, - substs: infcx.tcx.mk_substs_trait(ty, &[]), - }, + trait_ref: infcx.tcx.mk_trait_ref(trait_did, [ty]), + constness: ty::BoundConstness::NotConst, // Auto traits are positive polarity: ty::ImplPolarity::Positive, diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index f8346e515d70c..3a05708aebc6c 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -93,7 +93,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { def_id: DefId, ) { let tcx = self.infcx.tcx; - let trait_ref = ty::TraitRef { def_id, substs: tcx.mk_substs_trait(ty, &[]) }; + let trait_ref = tcx.mk_trait_ref(def_id, [ty]); self.register_obligation(Obligation { cause, recursion_depth: 0, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index c3547f64b5c9c..946e6e77a3da0 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -347,16 +347,12 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { span: DUMMY_SP, kind: TypeVariableOriginKind::MiscVariable, }); - let substs = self.tcx.mk_substs_trait(ty.skip_binder(), &[var.into()]); + let trait_ref = self.tcx.mk_trait_ref(trait_def_id, [ty.skip_binder(), var]); let obligation = Obligation::new( self.tcx, ObligationCause::dummy(), param_env, - ty.rebind(ty::TraitPredicate { - trait_ref: ty::TraitRef::new(trait_def_id, substs), - constness, - polarity, - }), + ty.rebind(ty::TraitPredicate { trait_ref, constness, polarity }), ); let mut fulfill_cx = >::new_in_snapshot(self.tcx); fulfill_cx.register_predicate_obligation(self, obligation); @@ -1001,12 +997,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if trait_predicate.skip_binder().self_ty().is_never() && self.fallback_has_occurred { - let predicate = trait_predicate.map_bound(|mut trait_pred| { - trait_pred.trait_ref.substs = self.tcx.mk_substs_trait( - self.tcx.mk_unit(), - &trait_pred.trait_ref.substs[1..], - ); - trait_pred + let predicate = trait_predicate.map_bound(|trait_pred| { + trait_pred.with_self_type(self.tcx, self.tcx.mk_unit()) }); let unit_obligation = obligation.with(tcx, predicate); if self.predicate_may_hold(&unit_obligation) { @@ -2028,13 +2020,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { param_env: ty::ParamEnv<'tcx>, trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>, ) -> PredicateObligation<'tcx> { - let trait_pred = trait_ref_and_ty.map_bound_ref(|(tr, new_self_ty)| ty::TraitPredicate { - trait_ref: ty::TraitRef { - substs: self.tcx.mk_substs_trait(*new_self_ty, &tr.trait_ref.substs[1..]), - ..tr.trait_ref - }, - ..*tr - }); + let trait_pred = trait_ref_and_ty + .map_bound(|(tr, new_self_ty)| tr.with_self_type(self.tcx, new_self_ty)); Obligation::new(self.tcx, ObligationCause::dummy(), param_env, trait_pred) } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 757977ac5d508..8086cac0d551a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2971,8 +2971,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); let impls_future = self.type_implements_trait( future_trait, - self.tcx.erase_late_bound_regions(self_ty), - ty::List::empty(), + [self.tcx.erase_late_bound_regions(self_ty)], obligation.param_env, ); if !impls_future.must_apply_modulo_regions() { @@ -2985,7 +2984,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.tcx.mk_projection( item_def_id, // Future::Output has no substs - self.tcx.mk_substs_trait(trait_pred.self_ty(), &[]), + self.tcx.mk_substs_trait(trait_pred.self_ty(), []), ) }); let projection_ty = normalize_to( @@ -3070,15 +3069,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let field_ty = field.ty(self.tcx, substs); let trait_substs = match diagnostic_name { sym::PartialEq | sym::PartialOrd => { - self.tcx.mk_substs_trait(field_ty, &[field_ty.into()]) + Some(field_ty) } - _ => self.tcx.mk_substs_trait(field_ty, &[]), + _ => None, }; let trait_pred = trait_pred.map_bound_ref(|tr| ty::TraitPredicate { - trait_ref: ty::TraitRef { - substs: trait_substs, - ..trait_pred.skip_binder().trait_ref - }, + trait_ref: self.tcx.mk_trait_ref( + trait_pred.def_id(), + [field_ty].into_iter().chain(trait_substs), + ), ..*tr }); let field_obl = Obligation::new( diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index ddc9b768f07e0..ff18aa1f9e909 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -136,7 +136,6 @@ pub fn predicates_for_generics<'tcx>( /// `bound` or is not known to meet bound (note that this is /// conservative towards *no impl*, which is the opposite of the /// `evaluate` methods). -#[instrument(level = "debug", skip(infcx, param_env, span), ret)] pub fn type_known_to_meet_bound_modulo_regions<'tcx>( infcx: &InferCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -144,33 +143,42 @@ pub fn type_known_to_meet_bound_modulo_regions<'tcx>( def_id: DefId, span: Span, ) -> bool { - let trait_ref = - ty::Binder::dummy(ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) }); + let trait_ref = ty::Binder::dummy(infcx.tcx.mk_trait_ref(def_id, [ty])); + pred_known_to_hold_modulo_regions(infcx, param_env, trait_ref.without_const(), span) +} + +#[instrument(level = "debug", skip(infcx, param_env, span, pred), ret)] +fn pred_known_to_hold_modulo_regions<'tcx>( + infcx: &InferCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + pred: impl ToPredicate<'tcx, ty::Predicate<'tcx>> + TypeVisitable<'tcx>, + span: Span, +) -> bool { + let has_non_region_infer = pred.has_non_region_infer(); let obligation = Obligation { param_env, + // We can use a dummy node-id here because we won't pay any mind + // to region obligations that arise (there shouldn't really be any + // anyhow). cause: ObligationCause::misc(span, hir::CRATE_HIR_ID), recursion_depth: 0, - predicate: trait_ref.without_const().to_predicate(infcx.tcx), + predicate: pred.to_predicate(infcx.tcx), }; let result = infcx.predicate_must_hold_modulo_regions(&obligation); debug!(?result); - if result && ty.has_non_region_infer() { + if result && has_non_region_infer { // Because of inference "guessing", selection can sometimes claim // to succeed while the success requires a guess. To ensure // this function's result remains infallible, we must confirm // that guess. While imperfect, I believe this is sound. - // We can use a dummy node-id here because we won't pay any mind - // to region obligations that arise (there shouldn't really be any - // anyhow). - let cause = ObligationCause::misc(span, hir::CRATE_HIR_ID); - + // FIXME(@lcnr): this function doesn't seem right. // The handling of regions in this area of the code is terrible, // see issue #29149. We should be able to improve on this with // NLL. - let errors = fully_solve_bound(infcx, cause, param_env, ty, def_id); + let errors = fully_solve_obligation(infcx, obligation); // Note: we only assume something is `Copy` if we can // *definitively* show that it implements `Copy`. Otherwise, @@ -895,10 +903,7 @@ pub fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>( // this has been typecked-before, so diagnostics is not really needed. let unsize_trait_did = tcx.require_lang_item(LangItem::Unsize, None); - let trait_ref = ty::TraitRef { - def_id: unsize_trait_did, - substs: tcx.mk_substs_trait(source, &[target.into()]), - }; + let trait_ref = tcx.mk_trait_ref(unsize_trait_did, [source, target]); match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), ty::Binder::dummy(trait_ref))) { Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => { diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 9745e0137ee9f..90f48658113af 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -685,10 +685,9 @@ fn receiver_is_dispatchable<'tcx>( let param_env = tcx.param_env(method.def_id); // Self: Unsize - let unsize_predicate = ty::Binder::dummy(ty::TraitRef { - def_id: unsize_did, - substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]), - }) + let unsize_predicate = ty::Binder::dummy( + tcx.mk_trait_ref(unsize_did, [tcx.types.self_param, unsized_self_ty]), + ) .without_const() .to_predicate(tcx); @@ -720,10 +719,9 @@ fn receiver_is_dispatchable<'tcx>( // Receiver: DispatchFromDyn U]> let obligation = { - let predicate = ty::Binder::dummy(ty::TraitRef { - def_id: dispatch_from_dyn_did, - substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]), - }) + let predicate = ty::Binder::dummy( + tcx.mk_trait_ref(dispatch_from_dyn_did, [receiver_ty, unsized_receiver_ty]), + ) .without_const(); Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 528b98cf4a1c0..9f19b0092c00f 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1710,9 +1710,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( if selcx.infcx().predicate_must_hold_modulo_regions( &obligation.with( selcx.tcx(), - ty::Binder::dummy(ty::TraitRef::new( - selcx.tcx().require_lang_item(LangItem::Sized, None), - selcx.tcx().mk_substs_trait(self_ty, &[]), + ty::Binder::dummy(selcx.tcx().at(obligation.cause.span).mk_trait_ref( + LangItem::Sized, + [self_ty], )) .without_const(), ), @@ -1966,16 +1966,15 @@ fn confirm_pointee_candidate<'cx, 'tcx>( ) }); if check_is_sized { - let sized_predicate = ty::Binder::dummy(ty::TraitRef::new( - tcx.require_lang_item(LangItem::Sized, None), - tcx.mk_substs_trait(self_ty, &[]), - )) + let sized_predicate = ty::Binder::dummy( + tcx.at(obligation.cause.span).mk_trait_ref(LangItem::Sized, [self_ty]), + ) .without_const(); obligations.push(obligation.with(tcx, sized_predicate)); } let substs = tcx.mk_substs([self_ty.into()].iter()); - let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, None); + let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, Some(obligation.cause.span)); let predicate = ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { substs, item_def_id: metadata_def_id }, diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs index dfe19a5a86d3b..f844da500328e 100644 --- a/compiler/rustc_trait_selection/src/traits/relationships.rs +++ b/compiler/rustc_trait_selection/src/traits/relationships.rs @@ -18,11 +18,6 @@ pub(crate) fn update<'tcx, T>( { let new_self_ty = infcx.tcx.types.unit; - let trait_ref = ty::TraitRef { - substs: infcx.tcx.mk_substs_trait(new_self_ty, &tpred.trait_ref.substs[1..]), - ..tpred.trait_ref - }; - // Then construct a new obligation with Self = () added // to the ParamEnv, and see if it holds. let o = obligation.with(infcx.tcx, @@ -31,11 +26,7 @@ pub(crate) fn update<'tcx, T>( .kind() .rebind( // (*) binder moved here - ty::PredicateKind::Trait(ty::TraitPredicate { - trait_ref, - constness: tpred.constness, - polarity: tpred.polarity, - }) + ty::PredicateKind::Trait(tpred.with_self_type(infcx.tcx, new_self_ty)) ), ); // Don't report overflow errors. Otherwise equivalent to may_hold. diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 8183f34bb3c93..99d4e47ffc16f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -714,10 +714,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } // - let trait_ref = ty::TraitRef { - def_id: tcx.lang_items().deref_trait()?, - substs: tcx.mk_substs_trait(ty, &[]), - }; + let trait_ref = tcx.mk_trait_ref(tcx.lang_items().deref_trait()?, [ty]); let obligation = traits::Obligation::new( tcx, diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index a496aed38ac17..2ec5d925b6900 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -632,10 +632,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { output_ty, &mut nested, ); - let tr = ty::Binder::dummy(ty::TraitRef::new( - self.tcx().require_lang_item(LangItem::Sized, None), - self.tcx().mk_substs_trait(output_ty, &[]), - )); + let tr = + ty::Binder::dummy(self.tcx().at(cause.span).mk_trait_ref(LangItem::Sized, [output_ty])); nested.push(Obligation::new( self.infcx.tcx, cause, @@ -996,10 +994,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); // We can only make objects from sized types. - let tr = ty::Binder::dummy(ty::TraitRef::new( - tcx.require_lang_item(LangItem::Sized, None), - tcx.mk_substs_trait(source, &[]), - )); + let tr = + ty::Binder::dummy(tcx.at(cause.span).mk_trait_ref(LangItem::Sized, [source])); nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx))); // If the type is `Foo + 'a`, ensure that the type @@ -1105,8 +1101,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.cause.clone(), obligation.predicate.def_id(), obligation.recursion_depth + 1, - source_tail, - &[target_tail.into()], + [source_tail, target_tail], )); } @@ -1136,8 +1131,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.cause.clone(), obligation.predicate.def_id(), obligation.recursion_depth + 1, - a_last, - &[b_last.into()], + [a_last, b_last], ) })); } @@ -1253,10 +1247,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { cause.clone(), obligation.recursion_depth + 1, self_ty.rebind(ty::TraitPredicate { - trait_ref: ty::TraitRef { - def_id: self.tcx().require_lang_item(LangItem::Destruct, None), - substs: self.tcx().mk_substs_trait(nested_ty, &[]), - }, + trait_ref: self + .tcx() + .at(cause.span) + .mk_trait_ref(LangItem::Destruct, [nested_ty]), constness: ty::BoundConstness::ConstIfConst, polarity: ty::ImplPolarity::Positive, }), @@ -1277,10 +1271,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // or it's an ADT (and we need to check for a custom impl during selection) _ => { let predicate = self_ty.rebind(ty::TraitPredicate { - trait_ref: ty::TraitRef { - def_id: self.tcx().require_lang_item(LangItem::Destruct, None), - substs: self.tcx().mk_substs_trait(nested_ty, &[]), - }, + trait_ref: self + .tcx() + .at(cause.span) + .mk_trait_ref(LangItem::Destruct, [nested_ty]), constness: ty::BoundConstness::ConstIfConst, polarity: ty::ImplPolarity::Positive, }); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index a9314b1b85e66..e54e290fb4b11 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2100,8 +2100,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { cause.clone(), trait_def_id, recursion_depth, - normalized_ty, - &[], + [normalized_ty], ); obligations.push(placeholder_obligation); obligations diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index ed47d2f83df65..895b84fd7e9df 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -238,11 +238,9 @@ pub fn predicate_for_trait_def<'tcx>( cause: ObligationCause<'tcx>, trait_def_id: DefId, recursion_depth: usize, - self_ty: Ty<'tcx>, - params: &[GenericArg<'tcx>], + params: impl IntoIterator>>, ) -> PredicateObligation<'tcx> { - let trait_ref = - ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(self_ty, params) }; + let trait_ref = tcx.mk_trait_ref(trait_def_id, params); predicate_for_trait_ref(tcx, cause, param_env, trait_ref, recursion_depth) } @@ -305,10 +303,7 @@ pub fn closure_trait_ref_and_return_type<'tcx>( TupleArgumentsFlag::Yes => tcx.intern_tup(sig.skip_binder().inputs()), }; debug_assert!(!self_ty.has_escaping_bound_vars()); - let trait_ref = ty::TraitRef { - def_id: fn_trait_def_id, - substs: tcx.mk_substs_trait(self_ty, &[arguments_tuple.into()]), - }; + let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty, arguments_tuple]); sig.map_bound(|sig| (trait_ref, sig.output())) } @@ -319,10 +314,7 @@ pub fn generator_trait_ref_and_outputs<'tcx>( sig: ty::PolyGenSig<'tcx>, ) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>)> { debug_assert!(!self_ty.has_escaping_bound_vars()); - let trait_ref = ty::TraitRef { - def_id: fn_trait_def_id, - substs: tcx.mk_substs_trait(self_ty, &[sig.skip_binder().resume_ty.into()]), - }; + let trait_ref = tcx.mk_trait_ref(fn_trait_def_id, [self_ty, sig.skip_binder().resume_ty]); sig.map_bound(|sig| (trait_ref, sig.yield_ty, sig.return_ty)) } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index fce92c66ee8c7..53783e1bc4b2c 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -421,10 +421,7 @@ impl<'tcx> WfPredicates<'tcx> { fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) { if !subty.has_escaping_bound_vars() { let cause = self.cause(cause); - let trait_ref = ty::TraitRef { - def_id: self.tcx.require_lang_item(LangItem::Sized, None), - substs: self.tcx.mk_substs_trait(subty, &[]), - }; + let trait_ref = self.tcx.at(cause.span).mk_trait_ref(LangItem::Sized, [subty]); self.out.push(traits::Obligation::with_depth( self.tcx, cause, diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 36bd466496e12..06a42a95d6061 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -689,7 +689,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders( // it on the impl. let Some(sized_trait) = tcx.lang_items().sized_trait() else { return vec![ty] }; - let sized_predicate = ty::Binder::dummy(ty::TraitRef { - def_id: sized_trait, - substs: tcx.mk_substs_trait(ty, &[]), - }) - .without_const() - .to_predicate(tcx); + let sized_predicate = ty::Binder::dummy(tcx.mk_trait_ref(sized_trait, [ty])) + .without_const() + .to_predicate(tcx); let predicates = tcx.predicates_of(adtdef.did()).predicates; if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] } } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 7c3eb4efbc984..581993ba7d863 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -60,10 +60,10 @@ pub trait InternAs { type Output; fn intern_with(self, f: F) -> Self::Output where - F: FnOnce(&T) -> R; + F: FnOnce(&[T]) -> R; } -impl InternAs<[T], R> for I +impl InternAs for I where E: InternIteratorElement, I: Iterator, diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 85bd8446640dd..05607d05ecf23 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -44,7 +44,7 @@ where discard_positive_impl: bool, ) -> Option { let tcx = self.cx.tcx; - let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) }; + let trait_ref = tcx.mk_trait_ref(trait_def_id, [ty]); if !self.cx.generated_synthetics.insert((ty, trait_def_id)) { debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref); return None; diff --git a/src/test/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs b/src/test/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs new file mode 100644 index 0000000000000..02599d7c05b59 --- /dev/null +++ b/src/test/ui/pattern/usefulness/const-partial_eq-fallback-ice.rs @@ -0,0 +1,18 @@ +#![allow(warnings)] + +struct MyType; + +impl PartialEq for MyType { + fn eq(&self, y: &usize) -> bool { + true + } +} + +const CONSTANT: &&MyType = &&MyType; + +fn main() { + if let CONSTANT = &&MyType { + //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]` + println!("did match!"); + } +} diff --git a/src/test/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/src/test/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr new file mode 100644 index 0000000000000..358421cd6d24c --- /dev/null +++ b/src/test/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr @@ -0,0 +1,8 @@ +error: to use a constant of type `MyType` in a pattern, `MyType` must be annotated with `#[derive(PartialEq, Eq)]` + --> $DIR/const-partial_eq-fallback-ice.rs:14:12 + | +LL | if let CONSTANT = &&MyType { + | ^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs index 4bd55c1429c3b..82d368bb8bc2c 100644 --- a/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs +++ b/src/tools/clippy/clippy_lints/src/bool_assert_comparison.rs @@ -59,7 +59,7 @@ fn is_impl_not_trait_with_bool_out(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { ) }) .map_or(false, |assoc_item| { - let proj = cx.tcx.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(ty, &[])); + let proj = cx.tcx.mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(ty, [])); let nty = cx.tcx.normalize_erasing_regions(cx.param_env, proj); nty.is_bool() diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 218dbeaddcade..c4e7f8bfe1e20 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -842,14 +842,10 @@ fn walk_parents<'tcx>( } else if let Some(trait_id) = cx.tcx.trait_of_item(id) && let arg_ty = cx.tcx.erase_regions(cx.typeck_results().expr_ty_adjusted(e)) && let ty::Ref(_, sub_ty, _) = *arg_ty.kind() - && let subs = match cx + && let subs = cx .typeck_results() - .node_substs_opt(parent.hir_id) - .and_then(|subs| subs.get(1..)) - { - Some(subs) => cx.tcx.mk_substs(subs.iter().copied()), - None => cx.tcx.mk_substs(std::iter::empty::>()), - } && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() { + .node_substs_opt(parent.hir_id).map(|subs| &subs[1..]).unwrap_or_default() + && let impl_ty = if cx.tcx.fn_sig(id).skip_binder().inputs()[0].is_ref() { // Trait methods taking `&self` sub_ty } else { @@ -858,7 +854,7 @@ fn walk_parents<'tcx>( } && impl_ty.is_ref() && let infcx = cx.tcx.infer_ctxt().build() && infcx - .type_implements_trait(trait_id, impl_ty, subs, cx.param_env) + .type_implements_trait(trait_id, [impl_ty.into()].into_iter().chain(subs.iter().copied()), cx.param_env) .must_apply_modulo_regions() { return Some(Position::MethodReceiverRefImpl) @@ -1263,7 +1259,7 @@ fn replace_types<'tcx>( let item_def_id = projection_predicate.projection_ty.item_def_id; let assoc_item = cx.tcx.associated_item(item_def_id); let projection = cx.tcx - .mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(new_ty, &[])); + .mk_projection(assoc_item.def_id, cx.tcx.mk_substs_trait(new_ty, [])); if let Ok(projected_ty) = cx.tcx.try_normalize_erasing_regions(cx.param_env, projection) && substs[term_param_ty.index as usize] != ty::GenericArg::from(projected_ty) diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index 102a02138bc87..1d9af7cdbd358 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -466,12 +466,12 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r if let Some(def_id) = trait_ref.trait_def_id(); if cx.tcx.is_diagnostic_item(sym::PartialEq, def_id); let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id); - if !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[]); + if !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, []); // If all of our fields implement `Eq`, we can implement `Eq` too if adt .all_fields() .map(|f| f.ty(cx.tcx, substs)) - .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[])); + .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, [])); then { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/eta_reduction.rs b/src/tools/clippy/clippy_lints/src/eta_reduction.rs index 7b9786d7e570f..f34cbee03558b 100644 --- a/src/tools/clippy/clippy_lints/src/eta_reduction.rs +++ b/src/tools/clippy/clippy_lints/src/eta_reduction.rs @@ -119,11 +119,13 @@ impl<'tcx> LateLintPass<'tcx> for EtaReduction { let callee_ty_unadjusted = cx.typeck_results().expr_ty(callee).peel_refs(); if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Arc); if !is_type_diagnostic_item(cx, callee_ty_unadjusted, sym::Rc); + if let ty::Closure(_, substs) = *closure_ty.kind(); then { span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure", |diag| { if let Some(mut snippet) = snippet_opt(cx, callee.span) { if let Some(fn_mut_id) = cx.tcx.lang_items().fn_mut_trait() - && implements_trait(cx, callee_ty.peel_refs(), fn_mut_id, &[]) + && let args = cx.tcx.erase_late_bound_regions(substs.as_closure().sig()).inputs() + && implements_trait(cx, callee_ty.peel_refs(), fn_mut_id, &args.iter().copied().map(Into::into).collect::>()) && path_to_local(callee).map_or(false, |l| local_used_after_expr(cx, l, expr)) { // Mutable closure is used after current expr; we cannot consume it. diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index c7775313ecd02..375ebc903b400 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -474,7 +474,7 @@ fn is_cow_into_owned(cx: &LateContext<'_>, method_name: Symbol, method_def_id: D } /// Returns true if the named method is `ToString::to_string` and it's called on a type that -/// is string-like i.e. implements `AsRef` or `Deref`. +/// is string-like i.e. implements `AsRef` or `Deref`. fn is_to_string_on_string_like<'a>( cx: &LateContext<'_>, call_expr: &'a Expr<'a>, @@ -490,7 +490,7 @@ fn is_to_string_on_string_like<'a>( && let GenericArgKind::Type(ty) = generic_arg.unpack() && let Some(deref_trait_id) = cx.tcx.get_diagnostic_item(sym::Deref) && let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef) - && (implements_trait(cx, ty, deref_trait_id, &[cx.tcx.types.str_.into()]) || + && (get_associated_type(cx, ty, deref_trait_id, "Target") == Some(cx.tcx.types.str_) || implements_trait(cx, ty, as_ref_trait_id, &[cx.tcx.types.str_.into()])) { true } else { diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 79aa15b06ef4d..eeff15bbfb422 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then}; use clippy_utils::ptr::get_spans; use clippy_utils::source::{snippet, snippet_opt}; -use clippy_utils::ty::{implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item}; +use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy, is_type_diagnostic_item, is_type_lang_item}; use clippy_utils::{get_trait_def_id, is_self, paths}; use if_chain::if_chain; use rustc_ast::ast::Attribute; @@ -185,7 +185,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { if !ty.is_mutable_ptr(); if !is_copy(cx, ty); if ty.is_sized(cx.tcx, cx.param_env); - if !allowed_traits.iter().any(|&t| implements_trait(cx, ty, t, &[])); + if !allowed_traits.iter().any(|&t| implements_trait_with_env(cx.tcx, cx.param_env, ty, t, [None])); if !implements_borrow_trait; if !all_borrowable_trait; diff --git a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 5c2b96f5b2ce6..a022fc156fca2 100644 --- a/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/src/tools/clippy/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -65,7 +65,7 @@ impl<'tcx> LateLintPass<'tcx> for NoNegCompOpForPartialOrd { let implements_partial_ord = { if let Some(id) = cx.tcx.lang_items().partial_ord_trait() { - implements_trait(cx, ty, id, &[]) + implements_trait(cx, ty, id, &[ty.into()]) } else { return; } diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index ea00650d42aa1..5420a0e782ea8 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -692,7 +692,7 @@ fn matches_preds<'tcx>( let infcx = cx.tcx.infer_ctxt().build(); preds.iter().all(|&p| match cx.tcx.erase_late_bound_regions(p) { ExistentialPredicate::Trait(p) => infcx - .type_implements_trait(p.def_id, ty, p.substs, cx.param_env) + .type_implements_trait(p.def_id, [ty.into()].into_iter().chain(p.substs.iter()), cx.param_env) .must_apply_modulo_regions(), ExistentialPredicate::Projection(p) => infcx.predicate_must_hold_modulo_regions(&Obligation::new( cx.tcx, @@ -704,7 +704,7 @@ fn matches_preds<'tcx>( )), )), ExistentialPredicate::AutoTrait(p) => infcx - .type_implements_trait(p, ty, List::empty(), cx.param_env) + .type_implements_trait(p, [ty], cx.param_env) .must_apply_modulo_regions(), }) } diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 3a144c2bb2239..5ec6f29fe9163 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -9,7 +9,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, FnDecl, LangItem, TyKind, Unsafety}; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{TyCtxtInferExt, type_variable::{TypeVariableOrigin, TypeVariableOriginKind}}; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{ConstValue, Scalar}; use rustc_middle::ty::{ @@ -18,7 +18,7 @@ use rustc_middle::ty::{ }; use rustc_middle::ty::{GenericArg, GenericArgKind}; use rustc_span::symbol::Ident; -use rustc_span::{sym, Span, Symbol}; +use rustc_span::{sym, Span, Symbol, DUMMY_SP}; use rustc_target::abi::{Size, VariantIdx}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::query::normalize::AtExt; @@ -79,7 +79,7 @@ pub fn get_associated_type<'tcx>( .associated_items(trait_id) .find_by_name_and_kind(cx.tcx, Ident::from_str(name), ty::AssocKind::Type, trait_id) .and_then(|assoc| { - let proj = cx.tcx.mk_projection(assoc.def_id, cx.tcx.mk_substs_trait(ty, &[])); + let proj = cx.tcx.mk_projection(assoc.def_id, cx.tcx.mk_substs_trait(ty, [])); cx.tcx.try_normalize_erasing_regions(cx.param_env, proj).ok() }) } @@ -153,7 +153,7 @@ pub fn implements_trait<'tcx>( trait_id: DefId, ty_params: &[GenericArg<'tcx>], ) -> bool { - implements_trait_with_env(cx.tcx, cx.param_env, ty, trait_id, ty_params) + implements_trait_with_env(cx.tcx, cx.param_env, ty, trait_id, ty_params.iter().map(|&arg| Some(arg))) } /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context. @@ -162,7 +162,7 @@ pub fn implements_trait_with_env<'tcx>( param_env: ParamEnv<'tcx>, ty: Ty<'tcx>, trait_id: DefId, - ty_params: &[GenericArg<'tcx>], + ty_params: impl IntoIterator>>, ) -> bool { // Clippy shouldn't have infer types assert!(!ty.needs_infer()); @@ -171,10 +171,14 @@ pub fn implements_trait_with_env<'tcx>( if ty.has_escaping_bound_vars() { return false; } - let ty_params = tcx.mk_substs(ty_params.iter()); let infcx = tcx.infer_ctxt().build(); + let orig = TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span: DUMMY_SP, + }; + let ty_params = tcx.mk_substs(ty_params.into_iter().map(|arg| arg.unwrap_or_else(|| infcx.next_ty_var(orig).into()))); infcx - .type_implements_trait(trait_id, ty, ty_params, param_env) + .type_implements_trait(trait_id, [ty.into()].into_iter().chain(ty_params), param_env) .must_apply_modulo_regions() }