Add helper to create the trait ref for a lang item
This commit is contained in:
parent
25c4760b5d
commit
ad57f88d3f
10 changed files with 51 additions and 66 deletions
|
@ -547,11 +547,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
|
||||||
|
|
||||||
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
|
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let trait_ref = tcx.mk_trait_ref(
|
let trait_ref = tcx.at(self.last_span).mk_trait_ref(LangItem::Copy, place_ty.ty, []);
|
||||||
tcx.require_lang_item(LangItem::Copy, Some(self.last_span)),
|
|
||||||
place_ty.ty,
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
// To have a `Copy` operand, the type `T` of the
|
// To have a `Copy` operand, the type `T` of the
|
||||||
// value must be `Copy`. Note that we prove that `T: Copy`,
|
// value must be `Copy`. Note that we prove that `T: Copy`,
|
||||||
|
@ -1274,11 +1270,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
|
|
||||||
self.check_rvalue(body, rv, location);
|
self.check_rvalue(body, rv, location);
|
||||||
if !self.unsized_feature_enabled() {
|
if !self.unsized_feature_enabled() {
|
||||||
let trait_ref = tcx.mk_trait_ref(
|
let trait_ref =
|
||||||
tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
|
tcx.at(self.last_span).mk_trait_ref(LangItem::Sized, place_ty, []);
|
||||||
place_ty,
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
self.prove_trait_ref(
|
self.prove_trait_ref(
|
||||||
trait_ref,
|
trait_ref,
|
||||||
location.to_locations(),
|
location.to_locations(),
|
||||||
|
@ -1842,6 +1835,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
#[instrument(skip(self, body), level = "debug")]
|
#[instrument(skip(self, body), level = "debug")]
|
||||||
fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
|
fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
let span = body.source_info(location).span;
|
||||||
|
|
||||||
match rvalue {
|
match rvalue {
|
||||||
Rvalue::Aggregate(ak, ops) => {
|
Rvalue::Aggregate(ak, ops) => {
|
||||||
|
@ -1865,13 +1859,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
Operand::Move(place) => {
|
Operand::Move(place) => {
|
||||||
// Make sure that repeated elements implement `Copy`.
|
// Make sure that repeated elements implement `Copy`.
|
||||||
let span = body.source_info(location).span;
|
|
||||||
let ty = place.ty(body, tcx).ty;
|
let ty = place.ty(body, tcx).ty;
|
||||||
let trait_ref = tcx.mk_trait_ref(
|
let trait_ref = tcx.at(span).mk_trait_ref(LangItem::Copy, ty, []);
|
||||||
tcx.require_lang_item(LangItem::Copy, Some(span)),
|
|
||||||
ty,
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
self.prove_trait_ref(
|
self.prove_trait_ref(
|
||||||
trait_ref,
|
trait_ref,
|
||||||
|
@ -1884,11 +1873,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
&Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
|
&Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
|
||||||
let trait_ref = tcx.mk_trait_ref(
|
let trait_ref = tcx.at(span).mk_trait_ref(LangItem::Sized, ty, []);
|
||||||
tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
|
|
||||||
ty,
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
self.prove_trait_ref(
|
self.prove_trait_ref(
|
||||||
trait_ref,
|
trait_ref,
|
||||||
|
@ -1900,11 +1885,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
Rvalue::ShallowInitBox(operand, ty) => {
|
Rvalue::ShallowInitBox(operand, ty) => {
|
||||||
self.check_operand(operand, location);
|
self.check_operand(operand, location);
|
||||||
|
|
||||||
let trait_ref = tcx.mk_trait_ref(
|
let trait_ref = tcx.at(span).mk_trait_ref(LangItem::Sized, *ty, []);
|
||||||
tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
|
|
||||||
*ty,
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
self.prove_trait_ref(
|
self.prove_trait_ref(
|
||||||
trait_ref,
|
trait_ref,
|
||||||
|
@ -2001,8 +1982,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
|
|
||||||
CastKind::Pointer(PointerCast::Unsize) => {
|
CastKind::Pointer(PointerCast::Unsize) => {
|
||||||
let &ty = ty;
|
let &ty = ty;
|
||||||
let trait_ref = tcx.mk_trait_ref(
|
let trait_ref = tcx.at(span).mk_trait_ref(
|
||||||
tcx.require_lang_item(LangItem::CoerceUnsized, Some(self.last_span)),
|
LangItem::CoerceUnsized,
|
||||||
op.ty(body, tcx),
|
op.ty(body, tcx),
|
||||||
[ty.into()],
|
[ty.into()],
|
||||||
);
|
);
|
||||||
|
|
|
@ -153,14 +153,12 @@ impl Qualif for NeedsNonConstDrop {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let destruct = cx.tcx.require_lang_item(LangItem::Destruct, None);
|
|
||||||
|
|
||||||
let obligation = Obligation::new(
|
let obligation = Obligation::new(
|
||||||
cx.tcx,
|
cx.tcx,
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy_with_span(cx.body.span),
|
||||||
cx.param_env,
|
cx.param_env,
|
||||||
ty::Binder::dummy(ty::TraitPredicate {
|
ty::Binder::dummy(ty::TraitPredicate {
|
||||||
trait_ref: cx.tcx.mk_trait_ref(destruct, ty, []),
|
trait_ref: cx.tcx.at(cx.body.span).mk_trait_ref(LangItem::Destruct, ty, []),
|
||||||
constness: ty::BoundConstness::ConstIfConst,
|
constness: ty::BoundConstness::ConstIfConst,
|
||||||
polarity: ty::ImplPolarity::Positive,
|
polarity: ty::ImplPolarity::Positive,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -60,10 +60,10 @@ impl<'tcx> Bounds<'tcx> {
|
||||||
{
|
{
|
||||||
// If it could be sized, and is, add the `Sized` predicate.
|
// If it could be sized, and is, add the `Sized` predicate.
|
||||||
let sized_predicate = self.implicitly_sized.and_then(|span| {
|
let sized_predicate = self.implicitly_sized.and_then(|span| {
|
||||||
tcx.lang_items().sized_trait().map(move |sized| {
|
// 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, []));
|
let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(sized, param_ty, []));
|
||||||
(trait_ref.without_const().to_predicate(tcx), span)
|
Some((trait_ref.without_const().to_predicate(tcx), span))
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let region_preds = self.region_bounds.iter().map(move |&(region_bound, span)| {
|
let region_preds = self.region_bounds.iter().map(move |&(region_bound, span)| {
|
||||||
|
|
|
@ -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.
|
// The first type is `receiver_ty`, which we know its not equal to `self_ty`; skip it.
|
||||||
autoderef.next();
|
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`.
|
// Keep dereferencing `receiver_ty` until we get to `self_ty`.
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -2990,6 +2990,16 @@ impl<'tcx> TyCtxtAt<'tcx> {
|
||||||
pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
|
pub fn ty_error_with_message(self, msg: &str) -> Ty<'tcx> {
|
||||||
self.tcx.ty_error_with_message(self.span, msg)
|
self.tcx.ty_error_with_message(self.span, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mk_trait_ref(
|
||||||
|
self,
|
||||||
|
trait_lang_item: LangItem,
|
||||||
|
self_ty: Ty<'tcx>,
|
||||||
|
rest: impl IntoIterator<Item = ty::GenericArg<'tcx>, IntoIter: ExactSizeIterator>,
|
||||||
|
) -> 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, self_ty, rest)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parameter attributes that can only be determined by examining the body of a function instead
|
/// Parameter attributes that can only be determined by examining the body of a function instead
|
||||||
|
|
|
@ -187,6 +187,7 @@ use rustc_middle::mir::visit::Visitor as MirVisitor;
|
||||||
use rustc_middle::mir::{self, Local, Location};
|
use rustc_middle::mir::{self, Local, Location};
|
||||||
use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast};
|
use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCast};
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
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::subst::{GenericArgKind, InternalSubsts};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitable, VtblEntry,
|
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 = operand.ty(self.body, self.tcx);
|
||||||
let source_ty = self.monomorphize(source_ty);
|
let source_ty = self.monomorphize(source_ty);
|
||||||
let (source_ty, target_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
|
// This could also be a different Unsize instruction, like
|
||||||
// from a fixed sized array to a slice. But we are only
|
// from a fixed sized array to a slice. But we are only
|
||||||
// interested in things that produce a vtable.
|
// 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
|
/// Finally, there is also the case of custom unsizing coercions, e.g., for
|
||||||
/// smart pointers such as `Rc` and `Arc`.
|
/// smart pointers such as `Rc` and `Arc`.
|
||||||
fn find_vtable_types_for_unsizing<'tcx>(
|
fn find_vtable_types_for_unsizing<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxtAt<'tcx>,
|
||||||
source_ty: Ty<'tcx>,
|
source_ty: Ty<'tcx>,
|
||||||
target_ty: Ty<'tcx>,
|
target_ty: Ty<'tcx>,
|
||||||
) -> (Ty<'tcx>, Ty<'tcx>) {
|
) -> (Ty<'tcx>, Ty<'tcx>) {
|
||||||
let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
|
let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
let type_has_metadata = |ty: Ty<'tcx>| -> bool {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env);
|
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(
|
find_vtable_types_for_unsizing(
|
||||||
tcx,
|
tcx,
|
||||||
source_fields[coerce_index].ty(tcx, source_substs),
|
source_fields[coerce_index].ty(*tcx, source_substs),
|
||||||
target_fields[coerce_index].ty(tcx, target_substs),
|
target_fields[coerce_index].ty(*tcx, target_substs),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => bug!(
|
_ => bug!(
|
||||||
|
|
|
@ -13,8 +13,8 @@ extern crate rustc_middle;
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_middle::traits;
|
use rustc_middle::traits;
|
||||||
use rustc_middle::ty::adjustment::CustomCoerceUnsized;
|
use rustc_middle::ty::adjustment::CustomCoerceUnsized;
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::{Providers, TyCtxtAt};
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty};
|
||||||
|
|
||||||
mod collector;
|
mod collector;
|
||||||
mod errors;
|
mod errors;
|
||||||
|
@ -23,13 +23,12 @@ mod polymorphize;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
fn custom_coerce_unsize_info<'tcx>(
|
fn custom_coerce_unsize_info<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxtAt<'tcx>,
|
||||||
source_ty: Ty<'tcx>,
|
source_ty: Ty<'tcx>,
|
||||||
target_ty: Ty<'tcx>,
|
target_ty: Ty<'tcx>,
|
||||||
) -> CustomCoerceUnsized {
|
) -> CustomCoerceUnsized {
|
||||||
let def_id = tcx.require_lang_item(LangItem::CoerceUnsized, None);
|
let trait_ref =
|
||||||
|
ty::Binder::dummy(tcx.mk_trait_ref(LangItem::CoerceUnsized, source_ty, [target_ty.into()]));
|
||||||
let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(def_id, source_ty, [target_ty.into()]));
|
|
||||||
|
|
||||||
match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) {
|
match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), trait_ref)) {
|
||||||
Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData {
|
Ok(traits::ImplSource::UserDefined(traits::ImplSourceUserDefinedData {
|
||||||
|
|
|
@ -1710,8 +1710,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||||
if selcx.infcx().predicate_must_hold_modulo_regions(
|
if selcx.infcx().predicate_must_hold_modulo_regions(
|
||||||
&obligation.with(
|
&obligation.with(
|
||||||
selcx.tcx(),
|
selcx.tcx(),
|
||||||
ty::Binder::dummy(selcx.tcx().mk_trait_ref(
|
ty::Binder::dummy(selcx.tcx().at(obligation.cause.span).mk_trait_ref(
|
||||||
selcx.tcx().require_lang_item(LangItem::Sized, None),
|
LangItem::Sized,
|
||||||
self_ty, [],
|
self_ty, [],
|
||||||
))
|
))
|
||||||
.without_const(),
|
.without_const(),
|
||||||
|
@ -1966,8 +1966,8 @@ fn confirm_pointee_candidate<'cx, 'tcx>(
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
if check_is_sized {
|
if check_is_sized {
|
||||||
let sized_predicate = ty::Binder::dummy(tcx.mk_trait_ref(
|
let sized_predicate = ty::Binder::dummy(tcx.at(obligation.cause.span).mk_trait_ref(
|
||||||
tcx.require_lang_item(LangItem::Sized, None),
|
LangItem::Sized,
|
||||||
self_ty,
|
self_ty,
|
||||||
[],
|
[],
|
||||||
))
|
))
|
||||||
|
@ -1976,7 +1976,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
let substs = tcx.mk_substs([self_ty.into()].iter());
|
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 {
|
let predicate = ty::ProjectionPredicate {
|
||||||
projection_ty: ty::ProjectionTy { substs, item_def_id: metadata_def_id },
|
projection_ty: ty::ProjectionTy { substs, item_def_id: metadata_def_id },
|
||||||
|
|
|
@ -632,8 +632,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
output_ty,
|
output_ty,
|
||||||
&mut nested,
|
&mut nested,
|
||||||
);
|
);
|
||||||
let tr = ty::Binder::dummy(self.tcx().mk_trait_ref(
|
let tr = ty::Binder::dummy(self.tcx().at(cause.span).mk_trait_ref(
|
||||||
self.tcx().require_lang_item(LangItem::Sized, None),
|
LangItem::Sized,
|
||||||
output_ty,
|
output_ty,
|
||||||
[],
|
[],
|
||||||
));
|
));
|
||||||
|
@ -997,11 +997,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
);
|
);
|
||||||
|
|
||||||
// We can only make objects from sized types.
|
// We can only make objects from sized types.
|
||||||
let tr = ty::Binder::dummy(tcx.mk_trait_ref(
|
let tr =
|
||||||
tcx.require_lang_item(LangItem::Sized, None),
|
ty::Binder::dummy(tcx.at(cause.span).mk_trait_ref(LangItem::Sized, source, []));
|
||||||
source,
|
|
||||||
[],
|
|
||||||
));
|
|
||||||
nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx)));
|
nested.push(predicate_to_obligation(tr.without_const().to_predicate(tcx)));
|
||||||
|
|
||||||
// If the type is `Foo + 'a`, ensure that the type
|
// If the type is `Foo + 'a`, ensure that the type
|
||||||
|
@ -1255,8 +1252,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
cause.clone(),
|
cause.clone(),
|
||||||
obligation.recursion_depth + 1,
|
obligation.recursion_depth + 1,
|
||||||
self_ty.rebind(ty::TraitPredicate {
|
self_ty.rebind(ty::TraitPredicate {
|
||||||
trait_ref: self.tcx().mk_trait_ref(
|
trait_ref: self.tcx().at(cause.span).mk_trait_ref(
|
||||||
self.tcx().require_lang_item(LangItem::Destruct, None),
|
LangItem::Destruct,
|
||||||
nested_ty,
|
nested_ty,
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
|
@ -1280,8 +1277,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// or it's an ADT (and we need to check for a custom impl during selection)
|
// or it's an ADT (and we need to check for a custom impl during selection)
|
||||||
_ => {
|
_ => {
|
||||||
let predicate = self_ty.rebind(ty::TraitPredicate {
|
let predicate = self_ty.rebind(ty::TraitPredicate {
|
||||||
trait_ref: self.tcx().mk_trait_ref(
|
trait_ref: self.tcx().at(cause.span).mk_trait_ref(
|
||||||
self.tcx().require_lang_item(LangItem::Destruct, None),
|
LangItem::Destruct,
|
||||||
nested_ty,
|
nested_ty,
|
||||||
[],
|
[],
|
||||||
),
|
),
|
||||||
|
|
|
@ -421,8 +421,7 @@ impl<'tcx> WfPredicates<'tcx> {
|
||||||
fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
|
fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
|
||||||
if !subty.has_escaping_bound_vars() {
|
if !subty.has_escaping_bound_vars() {
|
||||||
let cause = self.cause(cause);
|
let cause = self.cause(cause);
|
||||||
let trait_ref =
|
let trait_ref = self.tcx.at(cause.span).mk_trait_ref(LangItem::Sized, subty, []);
|
||||||
self.tcx.mk_trait_ref(self.tcx.require_lang_item(LangItem::Sized, None), subty, []);
|
|
||||||
self.out.push(traits::Obligation::with_depth(
|
self.out.push(traits::Obligation::with_depth(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
cause,
|
cause,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue