summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_traits/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:25 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:25 +0000
commit5363f350887b1e5b5dd21a86f88c8af9d7fea6da (patch)
tree35ca005eb6e0e9a1ba3bb5dbc033209ad445dc17 /compiler/rustc_traits/src
parentAdding debian version 1.66.0+dfsg1-1. (diff)
downloadrustc-5363f350887b1e5b5dd21a86f88c8af9d7fea6da.tar.xz
rustc-5363f350887b1e5b5dd21a86f88c8af9d7fea6da.zip
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_traits/src')
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs43
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs127
-rw-r--r--compiler/rustc_traits/src/codegen.rs88
-rw-r--r--compiler/rustc_traits/src/dropck_outlives.rs209
-rw-r--r--compiler/rustc_traits/src/evaluate_obligation.rs2
-rw-r--r--compiler/rustc_traits/src/implied_outlives_bounds.rs49
-rw-r--r--compiler/rustc_traits/src/lib.rs3
-rw-r--r--compiler/rustc_traits/src/normalize_erasing_regions.rs16
-rw-r--r--compiler/rustc_traits/src/normalize_projection_ty.rs7
-rw-r--r--compiler/rustc_traits/src/type_op.rs229
10 files changed, 394 insertions, 379 deletions
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index 0de28b826..344c8b93c 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -9,9 +9,9 @@
use rustc_middle::traits::ChalkRustInterner as RustInterner;
use rustc_middle::ty::{self, AssocKind, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
use rustc_middle::ty::{InternalSubsts, SubstsRef};
+use rustc_target::abi::{Integer, IntegerType};
use rustc_ast::ast;
-use rustc_attr as attr;
use rustc_hir::def_id::DefId;
@@ -142,6 +142,8 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
Some(CoerceUnsized)
} else if lang_items.dispatch_from_dyn_trait() == Some(def_id) {
Some(DispatchFromDyn)
+ } else if lang_items.tuple_trait() == Some(def_id) {
+ Some(Tuple)
} else {
None
};
@@ -216,21 +218,21 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
c: adt_def.repr().c(),
packed: adt_def.repr().packed(),
int: adt_def.repr().int.map(|i| match i {
- attr::IntType::SignedInt(ty) => match ty {
- ast::IntTy::Isize => int(chalk_ir::IntTy::Isize),
- ast::IntTy::I8 => int(chalk_ir::IntTy::I8),
- ast::IntTy::I16 => int(chalk_ir::IntTy::I16),
- ast::IntTy::I32 => int(chalk_ir::IntTy::I32),
- ast::IntTy::I64 => int(chalk_ir::IntTy::I64),
- ast::IntTy::I128 => int(chalk_ir::IntTy::I128),
+ IntegerType::Pointer(true) => int(chalk_ir::IntTy::Isize),
+ IntegerType::Pointer(false) => uint(chalk_ir::UintTy::Usize),
+ IntegerType::Fixed(i, true) => match i {
+ Integer::I8 => int(chalk_ir::IntTy::I8),
+ Integer::I16 => int(chalk_ir::IntTy::I16),
+ Integer::I32 => int(chalk_ir::IntTy::I32),
+ Integer::I64 => int(chalk_ir::IntTy::I64),
+ Integer::I128 => int(chalk_ir::IntTy::I128),
},
- attr::IntType::UnsignedInt(ty) => match ty {
- ast::UintTy::Usize => uint(chalk_ir::UintTy::Usize),
- ast::UintTy::U8 => uint(chalk_ir::UintTy::U8),
- ast::UintTy::U16 => uint(chalk_ir::UintTy::U16),
- ast::UintTy::U32 => uint(chalk_ir::UintTy::U32),
- ast::UintTy::U64 => uint(chalk_ir::UintTy::U64),
- ast::UintTy::U128 => uint(chalk_ir::UintTy::U128),
+ IntegerType::Fixed(i, false) => match i {
+ Integer::I8 => uint(chalk_ir::UintTy::U8),
+ Integer::I16 => uint(chalk_ir::UintTy::U16),
+ Integer::I32 => uint(chalk_ir::UintTy::U32),
+ Integer::I64 => uint(chalk_ir::UintTy::U64),
+ Integer::I128 => uint(chalk_ir::UintTy::U128),
},
}),
})
@@ -570,6 +572,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
CoerceUnsized => lang_items.coerce_unsized_trait(),
DiscriminantKind => lang_items.discriminant_kind_trait(),
DispatchFromDyn => lang_items.dispatch_from_dyn_trait(),
+ Tuple => lang_items.tuple_trait(),
};
def_id.map(chalk_ir::TraitId)
}
@@ -728,16 +731,16 @@ fn bound_vars_for_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx
ty::GenericParamDefKind::Lifetime => {
let br = ty::BoundRegion {
var: ty::BoundVar::from_usize(substs.len()),
- kind: ty::BrAnon(substs.len() as u32),
+ kind: ty::BrAnon(substs.len() as u32, None),
};
tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)).into()
}
ty::GenericParamDefKind::Const { .. } => tcx
- .mk_const(ty::ConstS {
- kind: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)),
- ty: tcx.type_of(param.def_id),
- })
+ .mk_const(
+ ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)),
+ tcx.type_of(param.def_id),
+ )
.into(),
})
}
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 45d5ea93d..c4ab86e9e 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -89,24 +89,32 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Ty(ty.lower_into(interner)))
}
- ty::PredicateKind::Trait(predicate) => chalk_ir::DomainGoal::FromEnv(
- chalk_ir::FromEnv::Trait(predicate.trait_ref.lower_into(interner)),
- ),
- ty::PredicateKind::RegionOutlives(predicate) => chalk_ir::DomainGoal::Holds(
- chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
- a: predicate.0.lower_into(interner),
- b: predicate.1.lower_into(interner),
- }),
- ),
- ty::PredicateKind::TypeOutlives(predicate) => chalk_ir::DomainGoal::Holds(
- chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
- ty: predicate.0.lower_into(interner),
- lifetime: predicate.1.lower_into(interner),
- }),
- ),
- ty::PredicateKind::Projection(predicate) => chalk_ir::DomainGoal::Holds(
- chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)),
- ),
+ ty::PredicateKind::Clause(ty::Clause::Trait(predicate)) => {
+ chalk_ir::DomainGoal::FromEnv(chalk_ir::FromEnv::Trait(
+ predicate.trait_ref.lower_into(interner),
+ ))
+ }
+ ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => {
+ chalk_ir::DomainGoal::Holds(chalk_ir::WhereClause::LifetimeOutlives(
+ chalk_ir::LifetimeOutlives {
+ a: predicate.0.lower_into(interner),
+ b: predicate.1.lower_into(interner),
+ },
+ ))
+ }
+ ty::PredicateKind::Clause(ty::Clause::TypeOutlives(predicate)) => {
+ chalk_ir::DomainGoal::Holds(chalk_ir::WhereClause::TypeOutlives(
+ chalk_ir::TypeOutlives {
+ ty: predicate.0.lower_into(interner),
+ lifetime: predicate.1.lower_into(interner),
+ },
+ ))
+ }
+ ty::PredicateKind::Clause(ty::Clause::Projection(predicate)) => {
+ chalk_ir::DomainGoal::Holds(chalk_ir::WhereClause::AliasEq(
+ predicate.lower_into(interner),
+ ))
+ }
ty::PredicateKind::WellFormed(arg) => match arg.unpack() {
ty::GenericArgKind::Type(ty) => chalk_ir::DomainGoal::WellFormed(
chalk_ir::WellFormed::Ty(ty.lower_into(interner)),
@@ -121,6 +129,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::InEnvironment<chalk_ir::Goal<RustInterner<'
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::Ambiguous
| ty::PredicateKind::ConstEquate(..) => bug!("unexpected predicate {}", predicate),
};
let value = chalk_ir::ProgramClauseImplication {
@@ -148,12 +157,12 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi
collect_bound_vars(interner, interner.tcx, self.kind());
let value = match predicate {
- ty::PredicateKind::Trait(predicate) => {
+ ty::PredicateKind::Clause(ty::Clause::Trait(predicate)) => {
chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
chalk_ir::WhereClause::Implemented(predicate.trait_ref.lower_into(interner)),
))
}
- ty::PredicateKind::RegionOutlives(predicate) => {
+ ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => {
chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
a: predicate.0.lower_into(interner),
@@ -161,7 +170,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi
}),
))
}
- ty::PredicateKind::TypeOutlives(predicate) => {
+ ty::PredicateKind::Clause(ty::Clause::TypeOutlives(predicate)) => {
chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
ty: predicate.0.lower_into(interner),
@@ -169,7 +178,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi
}),
))
}
- ty::PredicateKind::Projection(predicate) => {
+ ty::PredicateKind::Clause(ty::Clause::Projection(predicate)) => {
chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)),
))
@@ -212,6 +221,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::GoalData<RustInterner<'tcx>>> for ty::Predi
ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::ConstEvaluatable(..)
+ | ty::PredicateKind::Ambiguous
| ty::PredicateKind::ConstEquate(..) => {
chalk_ir::GoalData::All(chalk_ir::Goals::empty(interner))
}
@@ -411,7 +421,11 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty<RustInterner<'tcx>> {
TyKind::Closure(closure, substitution) => {
ty::Closure(closure.0, substitution.lower_into(interner))
}
- TyKind::Generator(..) => unimplemented!(),
+ TyKind::Generator(generator, substitution) => ty::Generator(
+ generator.0,
+ substitution.lower_into(interner),
+ ast::Movability::Static,
+ ),
TyKind::GeneratorWitness(..) => unimplemented!(),
TyKind::Never => ty::Never,
TyKind::Tuple(_len, substitution) => {
@@ -498,18 +512,15 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
ty::DebruijnIndex::from_u32(var.debruijn.depth()),
ty::BoundRegion {
var: ty::BoundVar::from_usize(var.index),
- kind: ty::BrAnon(var.index as u32),
+ kind: ty::BrAnon(var.index as u32, None),
},
),
chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(),
chalk_ir::LifetimeData::Placeholder(p) => ty::RePlaceholder(ty::Placeholder {
universe: ty::UniverseIndex::from_usize(p.ui.counter),
- name: ty::BoundRegionKind::BrAnon(p.idx as u32),
+ name: ty::BoundRegionKind::BrAnon(p.idx as u32, None),
}),
chalk_ir::LifetimeData::Static => return interner.tcx.lifetimes.re_static,
- chalk_ir::LifetimeData::Empty(_) => {
- bug!("Chalk should not have been passed an empty lifetime.")
- }
chalk_ir::LifetimeData::Erased => return interner.tcx.lifetimes.re_erased,
chalk_ir::LifetimeData::Phantom(void, _) => match *void {},
};
@@ -546,7 +557,7 @@ impl<'tcx> LowerInto<'tcx, ty::Const<'tcx>> for &chalk_ir::Const<RustInterner<'t
chalk_ir::ConstValue::Placeholder(_p) => unimplemented!(),
chalk_ir::ConstValue::Concrete(c) => ty::ConstKind::Value(c.interned),
};
- interner.tcx.mk_const(ty::ConstS { ty, kind })
+ interner.tcx.mk_const(kind, ty)
}
}
@@ -602,22 +613,22 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<'
let (predicate, binders, _named_regions) =
collect_bound_vars(interner, interner.tcx, self.kind());
let value = match predicate {
- ty::PredicateKind::Trait(predicate) => {
+ ty::PredicateKind::Clause(ty::Clause::Trait(predicate)) => {
Some(chalk_ir::WhereClause::Implemented(predicate.trait_ref.lower_into(interner)))
}
- ty::PredicateKind::RegionOutlives(predicate) => {
+ ty::PredicateKind::Clause(ty::Clause::RegionOutlives(predicate)) => {
Some(chalk_ir::WhereClause::LifetimeOutlives(chalk_ir::LifetimeOutlives {
a: predicate.0.lower_into(interner),
b: predicate.1.lower_into(interner),
}))
}
- ty::PredicateKind::TypeOutlives(predicate) => {
+ ty::PredicateKind::Clause(ty::Clause::TypeOutlives(predicate)) => {
Some(chalk_ir::WhereClause::TypeOutlives(chalk_ir::TypeOutlives {
ty: predicate.0.lower_into(interner),
lifetime: predicate.1.lower_into(interner),
}))
}
- ty::PredicateKind::Projection(predicate) => {
+ ty::PredicateKind::Clause(ty::Clause::Projection(predicate)) => {
Some(chalk_ir::WhereClause::AliasEq(predicate.lower_into(interner)))
}
ty::PredicateKind::WellFormed(_ty) => None,
@@ -628,6 +639,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<'
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::Ambiguous
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("unexpected predicate {}", &self)
}
@@ -637,7 +649,7 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_ir::QuantifiedWhereClause<RustInterner<'
}
impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<RustInterner<'tcx>>>>
- for &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>
+ for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>
{
fn lower_into(
self,
@@ -692,7 +704,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru
trait_id: chalk_ir::TraitId(def_id),
substitution: interner
.tcx
- .mk_substs_trait(self_ty, &[])
+ .mk_substs_trait(self_ty, [])
.lower_into(interner),
}),
),
@@ -737,26 +749,31 @@ impl<'tcx> LowerInto<'tcx, Option<chalk_solve::rust_ir::QuantifiedInlineBound<Ru
let (predicate, binders, _named_regions) =
collect_bound_vars(interner, interner.tcx, self.kind());
match predicate {
- ty::PredicateKind::Trait(predicate) => Some(chalk_ir::Binders::new(
- binders,
- chalk_solve::rust_ir::InlineBound::TraitBound(
- predicate.trait_ref.lower_into(interner),
- ),
- )),
- ty::PredicateKind::Projection(predicate) => Some(chalk_ir::Binders::new(
- binders,
- chalk_solve::rust_ir::InlineBound::AliasEqBound(predicate.lower_into(interner)),
- )),
- ty::PredicateKind::TypeOutlives(_predicate) => None,
+ ty::PredicateKind::Clause(ty::Clause::Trait(predicate)) => {
+ Some(chalk_ir::Binders::new(
+ binders,
+ chalk_solve::rust_ir::InlineBound::TraitBound(
+ predicate.trait_ref.lower_into(interner),
+ ),
+ ))
+ }
+ ty::PredicateKind::Clause(ty::Clause::Projection(predicate)) => {
+ Some(chalk_ir::Binders::new(
+ binders,
+ chalk_solve::rust_ir::InlineBound::AliasEqBound(predicate.lower_into(interner)),
+ ))
+ }
+ ty::PredicateKind::Clause(ty::Clause::TypeOutlives(_predicate)) => None,
ty::PredicateKind::WellFormed(_ty) => None,
- ty::PredicateKind::RegionOutlives(..)
+ ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::Ambiguous
| ty::PredicateKind::TypeWellFormedFromEnv(..) => {
bug!("unexpected predicate {}", &self)
}
@@ -933,7 +950,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
}
}
- ty::BoundRegionKind::BrAnon(var) => match self.parameters.entry(var) {
+ ty::BoundRegionKind::BrAnon(var, _) => match self.parameters.entry(var) {
Entry::Vacant(entry) => {
entry.insert(chalk_ir::VariableKind::Lifetime);
}
@@ -991,13 +1008,13 @@ impl<'a, 'tcx> TypeFolder<'tcx> for NamedBoundVarSubstitutor<'a, 'tcx> {
ty::ReLateBound(index, br) if index == self.binder_index => match br.kind {
ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
Some(idx) => {
- let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx) };
+ let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx, None) };
return self.tcx.mk_region(ty::ReLateBound(index, new_br));
}
None => panic!("Missing `BrNamed`."),
},
ty::BrEnv => unimplemented!(),
- ty::BrAnon(_) => {}
+ ty::BrAnon(..) => {}
},
_ => (),
};
@@ -1072,14 +1089,16 @@ impl<'tcx> TypeFolder<'tcx> for ParamsSubstitutor<'tcx> {
Some(idx) => {
let br = ty::BoundRegion {
var: ty::BoundVar::from_u32(*idx),
- kind: ty::BrAnon(*idx),
+ kind: ty::BrAnon(*idx, None),
};
self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
}
None => {
let idx = self.named_regions.len() as u32;
- let br =
- ty::BoundRegion { var: ty::BoundVar::from_u32(idx), kind: ty::BrAnon(idx) };
+ let br = ty::BoundRegion {
+ var: ty::BoundVar::from_u32(idx),
+ kind: ty::BrAnon(idx, None),
+ };
self.named_regions.insert(_re.def_id, idx);
self.tcx.mk_region(ty::ReLateBound(self.binder_index, br))
}
@@ -1156,7 +1175,7 @@ impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> {
match *r {
ty::RePlaceholder(p) if p.universe == self.universe_index => {
- if let ty::BoundRegionKind::BrAnon(anon) = p.name {
+ if let ty::BoundRegionKind::BrAnon(anon, _) = p.name {
self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon);
}
}
diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs
new file mode 100644
index 000000000..f8f74b732
--- /dev/null
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -0,0 +1,88 @@
+// This file contains various trait resolution methods used by codegen.
+// They all assume regions can be erased and monomorphic types. It
+// seems likely that they should eventually be merged into more
+// general routines.
+
+use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
+use rustc_infer::traits::FulfillmentErrorCode;
+use rustc_middle::traits::CodegenObligationError;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
+use rustc_trait_selection::traits::{
+ ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt,
+ Unimplemented,
+};
+
+/// Attempts to resolve an obligation to an `ImplSource`. The result is
+/// a shallow `ImplSource` resolution, meaning that we do not
+/// (necessarily) resolve all nested obligations on the impl. Note
+/// that type check should guarantee to us that all nested
+/// obligations *could be* resolved if we wanted to.
+///
+/// This also expects that `trait_ref` is fully normalized.
+pub fn codegen_select_candidate<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>),
+) -> Result<&'tcx ImplSource<'tcx, ()>, CodegenObligationError> {
+ // We expect the input to be fully normalized.
+ debug_assert_eq!(trait_ref, tcx.normalize_erasing_regions(param_env, trait_ref));
+
+ // Do the initial selection for the obligation. This yields the
+ // shallow result we are looking for -- that is, what specific impl.
+ let infcx = tcx
+ .infer_ctxt()
+ .ignoring_regions()
+ .with_opaque_type_inference(DefiningAnchor::Bubble)
+ .build();
+ //~^ HACK `Bubble` is required for
+ // this test to pass: type-alias-impl-trait/assoc-projection-ice.rs
+ let mut selcx = SelectionContext::new(&infcx);
+
+ let obligation_cause = ObligationCause::dummy();
+ let obligation = Obligation::new(tcx, obligation_cause, param_env, trait_ref);
+
+ let selection = match selcx.select(&obligation) {
+ Ok(Some(selection)) => selection,
+ Ok(None) => return Err(CodegenObligationError::Ambiguity),
+ Err(Unimplemented) => return Err(CodegenObligationError::Unimplemented),
+ Err(e) => {
+ bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
+ }
+ };
+
+ debug!(?selection);
+
+ // Currently, we use a fulfillment context to completely resolve
+ // all nested obligations. This is because they can inform the
+ // inference of the impl's type parameters.
+ let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
+ let impl_source = selection.map(|predicate| {
+ fulfill_cx.register_predicate_obligation(&infcx, predicate);
+ });
+
+ // In principle, we only need to do this so long as `impl_source`
+ // contains unbound type parameters. It could be a slight
+ // optimization to stop iterating early.
+ let errors = fulfill_cx.select_all_or_error(&infcx);
+ if !errors.is_empty() {
+ // `rustc_monomorphize::collector` assumes there are no type errors.
+ // Cycle errors are the only post-monomorphization errors possible; emit them now so
+ // `rustc_ty_utils::resolve_associated_item` doesn't return `None` post-monomorphization.
+ for err in errors {
+ if let FulfillmentErrorCode::CodeCycle(cycle) = err.code {
+ infcx.err_ctxt().report_overflow_obligation_cycle(&cycle);
+ }
+ }
+ return Err(CodegenObligationError::FulfillmentError);
+ }
+
+ let impl_source = infcx.resolve_vars_if_possible(impl_source);
+ let impl_source = infcx.tcx.erase_regions(impl_source);
+
+ // Opaque types may have gotten their hidden types constrained, but we can ignore them safely
+ // as they will get constrained elsewhere, too.
+ // (ouz-a) This is required for `type-alias-impl-trait/assoc-projection-ice.rs` to pass
+ let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+
+ Ok(&*tcx.arena.alloc(impl_source))
+}
diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs
index d5a8ca5ea..66ab742f1 100644
--- a/compiler/rustc_traits/src/dropck_outlives.rs
+++ b/compiler/rustc_traits/src/dropck_outlives.rs
@@ -2,20 +2,18 @@ use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::TraitEngineExt as _;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::InternalSubsts;
use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt};
use rustc_span::source_map::{Span, DUMMY_SP};
+use rustc_trait_selection::infer::InferCtxtBuilderExt;
use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives;
use rustc_trait_selection::traits::query::dropck_outlives::{
DropckConstraint, DropckOutlivesResult,
};
-use rustc_trait_selection::traits::query::normalize::AtExt;
+use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution};
-use rustc_trait_selection::traits::{
- Normalized, ObligationCause, TraitEngine, TraitEngineExt as _,
-};
+use rustc_trait_selection::traits::{Normalized, ObligationCause};
pub(crate) fn provide(p: &mut Providers) {
*p = Providers { dropck_outlives, adt_dtorck_constraint, ..*p };
@@ -27,120 +25,109 @@ fn dropck_outlives<'tcx>(
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, NoSolution> {
debug!("dropck_outlives(goal={:#?})", canonical_goal);
- let (ref infcx, goal, canonical_inference_vars) =
- tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal);
- let tcx = infcx.tcx;
- let ParamEnvAnd { param_env, value: for_ty } = goal;
-
- let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
-
- // A stack of types left to process. Each round, we pop
- // something from the stack and invoke
- // `dtorck_constraint_for_ty`. This may produce new types that
- // have to be pushed on the stack. This continues until we have explored
- // all the reachable types from the type `for_ty`.
- //
- // Example: Imagine that we have the following code:
- //
- // ```rust
- // struct A {
- // value: B,
- // children: Vec<A>,
- // }
- //
- // struct B {
- // value: u32
- // }
- //
- // fn f() {
- // let a: A = ...;
- // ..
- // } // here, `a` is dropped
- // ```
- //
- // at the point where `a` is dropped, we need to figure out
- // which types inside of `a` contain region data that may be
- // accessed by any destructors in `a`. We begin by pushing `A`
- // onto the stack, as that is the type of `a`. We will then
- // invoke `dtorck_constraint_for_ty` which will expand `A`
- // into the types of its fields `(B, Vec<A>)`. These will get
- // pushed onto the stack. Eventually, expanding `Vec<A>` will
- // lead to us trying to push `A` a second time -- to prevent
- // infinite recursion, we notice that `A` was already pushed
- // once and stop.
- let mut ty_stack = vec![(for_ty, 0)];
-
- // Set used to detect infinite recursion.
- let mut ty_set = FxHashSet::default();
-
- let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
-
- let cause = ObligationCause::dummy();
- let mut constraints = DropckConstraint::empty();
- while let Some((ty, depth)) = ty_stack.pop() {
- debug!(
- "{} kinds, {} overflows, {} ty_stack",
- result.kinds.len(),
- result.overflows.len(),
- ty_stack.len()
- );
- dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
-
- // "outlives" represent types/regions that may be touched
- // by a destructor.
- result.kinds.append(&mut constraints.outlives);
- result.overflows.append(&mut constraints.overflows);
-
- // If we have even one overflow, we should stop trying to evaluate further --
- // chances are, the subsequent overflows for this evaluation won't provide useful
- // information and will just decrease the speed at which we can emit these errors
- // (since we'll be printing for just that much longer for the often enormous types
- // that result here).
- if !result.overflows.is_empty() {
- break;
- }
+ tcx.infer_ctxt().enter_canonical_trait_query(&canonical_goal, |ocx, goal| {
+ let tcx = ocx.infcx.tcx;
+ let ParamEnvAnd { param_env, value: for_ty } = goal;
+
+ let mut result = DropckOutlivesResult { kinds: vec![], overflows: vec![] };
+
+ // A stack of types left to process. Each round, we pop
+ // something from the stack and invoke
+ // `dtorck_constraint_for_ty`. This may produce new types that
+ // have to be pushed on the stack. This continues until we have explored
+ // all the reachable types from the type `for_ty`.
+ //
+ // Example: Imagine that we have the following code:
+ //
+ // ```rust
+ // struct A {
+ // value: B,
+ // children: Vec<A>,
+ // }
+ //
+ // struct B {
+ // value: u32
+ // }
+ //
+ // fn f() {
+ // let a: A = ...;
+ // ..
+ // } // here, `a` is dropped
+ // ```
+ //
+ // at the point where `a` is dropped, we need to figure out
+ // which types inside of `a` contain region data that may be
+ // accessed by any destructors in `a`. We begin by pushing `A`
+ // onto the stack, as that is the type of `a`. We will then
+ // invoke `dtorck_constraint_for_ty` which will expand `A`
+ // into the types of its fields `(B, Vec<A>)`. These will get
+ // pushed onto the stack. Eventually, expanding `Vec<A>` will
+ // lead to us trying to push `A` a second time -- to prevent
+ // infinite recursion, we notice that `A` was already pushed
+ // once and stop.
+ let mut ty_stack = vec![(for_ty, 0)];
+
+ // Set used to detect infinite recursion.
+ let mut ty_set = FxHashSet::default();
+
+ let cause = ObligationCause::dummy();
+ let mut constraints = DropckConstraint::empty();
+ while let Some((ty, depth)) = ty_stack.pop() {
+ debug!(
+ "{} kinds, {} overflows, {} ty_stack",
+ result.kinds.len(),
+ result.overflows.len(),
+ ty_stack.len()
+ );
+ dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?;
+
+ // "outlives" represent types/regions that may be touched
+ // by a destructor.
+ result.kinds.append(&mut constraints.outlives);
+ result.overflows.append(&mut constraints.overflows);
+
+ // If we have even one overflow, we should stop trying to evaluate further --
+ // chances are, the subsequent overflows for this evaluation won't provide useful
+ // information and will just decrease the speed at which we can emit these errors
+ // (since we'll be printing for just that much longer for the often enormous types
+ // that result here).
+ if !result.overflows.is_empty() {
+ break;
+ }
- // dtorck types are "types that will get dropped but which
- // do not themselves define a destructor", more or less. We have
- // to push them onto the stack to be expanded.
- for ty in constraints.dtorck_types.drain(..) {
- match infcx.at(&cause, param_env).normalize(ty) {
- Ok(Normalized { value: ty, obligations }) => {
- fulfill_cx.register_predicate_obligations(infcx, obligations);
-
- debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
-
- match ty.kind() {
- // All parameters live for the duration of the
- // function.
- ty::Param(..) => {}
-
- // A projection that we couldn't resolve - it
- // might have a destructor.
- ty::Projection(..) | ty::Opaque(..) => {
- result.kinds.push(ty.into());
- }
+ // dtorck types are "types that will get dropped but which
+ // do not themselves define a destructor", more or less. We have
+ // to push them onto the stack to be expanded.
+ for ty in constraints.dtorck_types.drain(..) {
+ let Normalized { value: ty, obligations } =
+ ocx.infcx.at(&cause, param_env).query_normalize(ty)?;
+ ocx.register_obligations(obligations);
+
+ debug!("dropck_outlives: ty from dtorck_types = {:?}", ty);
+
+ match ty.kind() {
+ // All parameters live for the duration of the
+ // function.
+ ty::Param(..) => {}
+
+ // A projection that we couldn't resolve - it
+ // might have a destructor.
+ ty::Projection(..) | ty::Opaque(..) => {
+ result.kinds.push(ty.into());
+ }
- _ => {
- if ty_set.insert(ty) {
- ty_stack.push((ty, depth + 1));
- }
+ _ => {
+ if ty_set.insert(ty) {
+ ty_stack.push((ty, depth + 1));
}
}
}
-
- // We don't actually expect to fail to normalize.
- // That implies a WF error somewhere else.
- Err(NoSolution) => {
- return Err(NoSolution);
- }
}
}
- }
-
- debug!("dropck_outlives: result = {:#?}", result);
- infcx.make_canonicalized_query_response(canonical_inference_vars, result, &mut *fulfill_cx)
+ debug!("dropck_outlives: result = {:#?}", result);
+ Ok(result)
+ })
}
/// Returns a set of constraints that needs to be satisfied in
diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs
index 493d5de08..e94c8efe6 100644
--- a/compiler/rustc_traits/src/evaluate_obligation.rs
+++ b/compiler/rustc_traits/src/evaluate_obligation.rs
@@ -26,7 +26,7 @@ fn evaluate_obligation<'tcx>(
let ParamEnvAnd { param_env, value: predicate } = goal;
let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical);
- let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);
+ let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate);
selcx.evaluate_root_obligation(&obligation)
}
diff --git a/compiler/rustc_traits/src/implied_outlives_bounds.rs b/compiler/rustc_traits/src/implied_outlives_bounds.rs
index 7d36b9558..010233d77 100644
--- a/compiler/rustc_traits/src/implied_outlives_bounds.rs
+++ b/compiler/rustc_traits/src/implied_outlives_bounds.rs
@@ -5,16 +5,15 @@
use rustc_hir as hir;
use rustc_infer::infer::canonical::{self, Canonical};
use rustc_infer::infer::outlives::components::{push_outlives_components, Component};
-use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::query::OutlivesBound;
-use rustc_infer::traits::TraitEngineExt as _;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable};
use rustc_span::source_map::DUMMY_SP;
use rustc_trait_selection::infer::InferCtxtBuilderExt;
use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution};
use rustc_trait_selection::traits::wf;
-use rustc_trait_selection::traits::{TraitEngine, TraitEngineExt};
+use rustc_trait_selection::traits::ObligationCtxt;
use smallvec::{smallvec, SmallVec};
pub(crate) fn provide(p: &mut Providers) {
@@ -28,18 +27,18 @@ fn implied_outlives_bounds<'tcx>(
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec<OutlivesBound<'tcx>>>>,
NoSolution,
> {
- tcx.infer_ctxt().enter_canonical_trait_query(&goal, |infcx, _fulfill_cx, key| {
+ tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| {
let (param_env, ty) = key.into_parts();
- compute_implied_outlives_bounds(&infcx, param_env, ty)
+ compute_implied_outlives_bounds(ocx, param_env, ty)
})
}
fn compute_implied_outlives_bounds<'tcx>(
- infcx: &InferCtxt<'tcx>,
+ ocx: &ObligationCtxt<'_, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
ty: Ty<'tcx>,
) -> Fallible<Vec<OutlivesBound<'tcx>>> {
- let tcx = infcx.tcx;
+ let tcx = ocx.infcx.tcx;
// Sometimes when we ask what it takes for T: WF, we get back that
// U: WF is required; in that case, we push U onto this stack and
@@ -52,8 +51,6 @@ fn compute_implied_outlives_bounds<'tcx>(
let mut outlives_bounds: Vec<ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>> =
vec![];
- let mut fulfill_cx = <dyn TraitEngine<'tcx>>::new(tcx);
-
while let Some(arg) = wf_args.pop() {
if !checked_wf_args.insert(arg) {
continue;
@@ -70,15 +67,15 @@ fn compute_implied_outlives_bounds<'tcx>(
// FIXME(@lcnr): It's not really "always fine", having fewer implied
// bounds can be backward incompatible, e.g. #101951 was caused by
// us not dealing with inference vars in `TypeOutlives` predicates.
- let obligations = wf::obligations(infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP)
- .unwrap_or_default();
+ let obligations =
+ wf::obligations(ocx.infcx, param_env, hir::CRATE_HIR_ID, 0, arg, DUMMY_SP)
+ .unwrap_or_default();
// While these predicates should all be implied by other parts of
// the program, they are still relevant as they may constrain
// inference variables, which is necessary to add the correct
// implied bounds in some cases, mostly when dealing with projections.
- fulfill_cx.register_predicate_obligations(
- infcx,
+ ocx.register_obligations(
obligations.iter().filter(|o| o.predicate.has_non_region_infer()).cloned(),
);
@@ -89,35 +86,37 @@ fn compute_implied_outlives_bounds<'tcx>(
match obligation.predicate.kind().no_bound_vars() {
None => None,
Some(pred) => match pred {
- ty::PredicateKind::Trait(..)
+ ty::PredicateKind::Clause(ty::Clause::Trait(..))
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
- | ty::PredicateKind::Projection(..)
+ | ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::Ambiguous
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
ty::PredicateKind::WellFormed(arg) => {
wf_args.push(arg);
None
}
- ty::PredicateKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
- Some(ty::OutlivesPredicate(r_a.into(), r_b))
- }
+ ty::PredicateKind::Clause(ty::Clause::RegionOutlives(
+ ty::OutlivesPredicate(r_a, r_b),
+ )) => Some(ty::OutlivesPredicate(r_a.into(), r_b)),
- ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty_a, r_b)) => {
- Some(ty::OutlivesPredicate(ty_a.into(), r_b))
- }
+ ty::PredicateKind::Clause(ty::Clause::TypeOutlives(ty::OutlivesPredicate(
+ ty_a,
+ r_b,
+ ))) => Some(ty::OutlivesPredicate(ty_a.into(), r_b)),
},
}
}));
}
- // Ensure that those obligations that we had to solve
- // get solved *here*.
- match fulfill_cx.select_all_or_error(infcx).as_slice() {
+ // This call to `select_all_or_error` is necessary to constrain inference variables, which we
+ // use further down when computing the implied bounds.
+ match ocx.select_all_or_error().as_slice() {
[] => (),
_ => return Err(NoSolution),
}
@@ -129,7 +128,7 @@ fn compute_implied_outlives_bounds<'tcx>(
.flat_map(|ty::OutlivesPredicate(a, r_b)| match a.unpack() {
ty::GenericArgKind::Lifetime(r_a) => vec![OutlivesBound::RegionSubRegion(r_b, r_a)],
ty::GenericArgKind::Type(ty_a) => {
- let ty_a = infcx.resolve_vars_if_possible(ty_a);
+ let ty_a = ocx.infcx.resolve_vars_if_possible(ty_a);
let mut components = smallvec![];
push_outlives_components(tcx, ty_a, &mut components);
implied_bounds_from_components(r_b, components)
diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs
index 0da28737f..9aa26667e 100644
--- a/compiler/rustc_traits/src/lib.rs
+++ b/compiler/rustc_traits/src/lib.rs
@@ -3,6 +3,7 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
+#![feature(let_chains)]
#![recursion_limit = "256"]
#[macro_use]
@@ -11,6 +12,7 @@ extern crate tracing;
extern crate rustc_middle;
mod chalk;
+mod codegen;
mod dropck_outlives;
mod evaluate_obligation;
mod implied_outlives_bounds;
@@ -30,4 +32,5 @@ pub fn provide(p: &mut Providers) {
normalize_projection_ty::provide(p);
normalize_erasing_regions::provide(p);
type_op::provide(p);
+ p.codegen_select_candidate = codegen::codegen_select_candidate;
}
diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs
index 2da64d73d..44fd8bfb3 100644
--- a/compiler/rustc_traits/src/normalize_erasing_regions.rs
+++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs
@@ -2,7 +2,7 @@ use rustc_infer::infer::TyCtxtInferExt;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt, TypeFoldable};
-use rustc_trait_selection::traits::query::normalize::AtExt;
+use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use rustc_trait_selection::traits::{Normalized, ObligationCause};
use std::sync::atomic::Ordering;
@@ -29,12 +29,14 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq +
let ParamEnvAnd { param_env, value } = goal;
let infcx = tcx.infer_ctxt().build();
let cause = ObligationCause::dummy();
- match infcx.at(&cause, param_env).normalize(value) {
+ match infcx.at(&cause, param_env).query_normalize(value) {
Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => {
// We don't care about the `obligations`; they are
// always only region relations, and we are about to
// erase those anyway:
- debug_assert_eq!(
+ // This has been seen to fail in RL, so making it a non-debug assertion to better catch
+ // those cases.
+ assert_eq!(
normalized_obligations.iter().find(|p| not_outlives_predicate(p.predicate)),
None,
);
@@ -54,9 +56,10 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq +
fn not_outlives_predicate<'tcx>(p: ty::Predicate<'tcx>) -> bool {
match p.kind().skip_binder() {
- ty::PredicateKind::RegionOutlives(..) | ty::PredicateKind::TypeOutlives(..) => false,
- ty::PredicateKind::Trait(..)
- | ty::PredicateKind::Projection(..)
+ ty::PredicateKind::Clause(ty::Clause::RegionOutlives(..))
+ | ty::PredicateKind::Clause(ty::Clause::TypeOutlives(..)) => false,
+ ty::PredicateKind::Clause(ty::Clause::Trait(..))
+ | ty::PredicateKind::Clause(ty::Clause::Projection(..))
| ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
@@ -64,6 +67,7 @@ fn not_outlives_predicate<'tcx>(p: ty::Predicate<'tcx>) -> bool {
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
+ | ty::PredicateKind::Ambiguous
| ty::PredicateKind::TypeWellFormedFromEnv(..) => true,
}
}
diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs
index 98bb42c9a..e805eb428 100644
--- a/compiler/rustc_traits/src/normalize_projection_ty.rs
+++ b/compiler/rustc_traits/src/normalize_projection_ty.rs
@@ -1,6 +1,5 @@
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
use rustc_infer::infer::TyCtxtInferExt;
-use rustc_infer::traits::TraitEngineExt as _;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
use rustc_trait_selection::infer::InferCtxtBuilderExt;
@@ -23,8 +22,8 @@ fn normalize_projection_ty<'tcx>(
tcx.sess.perf_stats.normalize_projection_ty.fetch_add(1, Ordering::Relaxed);
tcx.infer_ctxt().enter_canonical_trait_query(
&goal,
- |infcx, fulfill_cx, ParamEnvAnd { param_env, value: goal }| {
- let selcx = &mut SelectionContext::new(infcx);
+ |ocx, ParamEnvAnd { param_env, value: goal }| {
+ let selcx = &mut SelectionContext::new(ocx.infcx);
let cause = ObligationCause::dummy();
let mut obligations = vec![];
let answer = traits::normalize_projection_type(
@@ -35,7 +34,7 @@ fn normalize_projection_ty<'tcx>(
0,
&mut obligations,
);
- fulfill_cx.register_predicate_obligations(infcx, obligations);
+ ocx.register_obligations(obligations);
// FIXME(associated_const_equality): All users of normalize_projection_ty expected
// a type, but there is the possibility it could've been a const now. Maybe change
// it to a Term later?
diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs
index bca7458ed..7f964afde 100644
--- a/compiler/rustc_traits/src/type_op.rs
+++ b/compiler/rustc_traits/src/type_op.rs
@@ -1,26 +1,21 @@
use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
-use rustc_infer::infer::at::ToTrace;
use rustc_infer::infer::canonical::{Canonical, QueryResponse};
-use rustc_infer::infer::{DefiningAnchor, InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::{ObligationCauseCode, TraitEngineExt as _};
+use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
+use rustc_infer::traits::ObligationCauseCode;
use rustc_middle::ty::query::Providers;
-use rustc_middle::ty::{
- self, EarlyBinder, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable, Variance,
-};
-use rustc_middle::ty::{GenericArg, UserSelfTy, UserSubsts};
-use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Predicate, ToPredicate};
+use rustc_middle::ty::{self, FnSig, Lift, PolyFnSig, Ty, TyCtxt, TypeFoldable};
+use rustc_middle::ty::{ParamEnvAnd, Predicate, ToPredicate};
+use rustc_middle::ty::{UserSelfTy, UserSubsts};
use rustc_span::{Span, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtBuilderExt;
-use rustc_trait_selection::infer::InferCtxtExt;
-use rustc_trait_selection::traits::query::normalize::AtExt;
+use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use rustc_trait_selection::traits::query::type_op::ascribe_user_type::AscribeUserType;
use rustc_trait_selection::traits::query::type_op::eq::Eq;
use rustc_trait_selection::traits::query::type_op::normalize::Normalize;
use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate;
use rustc_trait_selection::traits::query::type_op::subtype::Subtype;
use rustc_trait_selection::traits::query::{Fallible, NoSolution};
-use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, TraitEngine};
+use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, ObligationCtxt};
use std::fmt;
use std::iter::zip;
@@ -42,17 +37,16 @@ fn type_op_ascribe_user_type<'tcx>(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, AscribeUserType<'tcx>>>,
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
- tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
- type_op_ascribe_user_type_with_span(infcx, fulfill_cx, key, None)
+ tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| {
+ type_op_ascribe_user_type_with_span(ocx, key, None)
})
}
/// The core of the `type_op_ascribe_user_type` query: for diagnostics purposes in NLL HRTB errors,
/// this query can be re-run to better track the span of the obligation cause, and improve the error
/// message. Do not call directly unless you're in that very specific context.
-pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>(
- infcx: &'a InferCtxt<'tcx>,
- fulfill_cx: &'a mut dyn TraitEngine<'tcx>,
+pub fn type_op_ascribe_user_type_with_span<'tcx>(
+ ocx: &ObligationCtxt<'_, 'tcx>,
key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>,
span: Option<Span>,
) -> Result<(), NoSolution> {
@@ -61,157 +55,81 @@ pub fn type_op_ascribe_user_type_with_span<'a, 'tcx: 'a>(
"type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}",
mir_ty, def_id, user_substs
);
+ let span = span.unwrap_or(DUMMY_SP);
- let mut cx = AscribeUserTypeCx { infcx, param_env, span: span.unwrap_or(DUMMY_SP), fulfill_cx };
- cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?;
- Ok(())
-}
+ let UserSubsts { user_self_ty, substs } = user_substs;
+ let tcx = ocx.infcx.tcx;
+ let cause = ObligationCause::dummy_with_span(span);
-struct AscribeUserTypeCx<'me, 'tcx> {
- infcx: &'me InferCtxt<'tcx>,
- param_env: ParamEnv<'tcx>,
- span: Span,
- fulfill_cx: &'me mut dyn TraitEngine<'tcx>,
-}
+ let ty = tcx.bound_type_of(def_id).subst(tcx, substs);
+ let ty = ocx.normalize(&cause, param_env, ty);
+ debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
-impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> {
- fn normalize<T>(&mut self, value: T) -> T
- where
- T: TypeFoldable<'tcx>,
- {
- self.normalize_with_cause(value, ObligationCause::misc(self.span, hir::CRATE_HIR_ID))
- }
+ ocx.eq(&cause, param_env, mir_ty, ty)?;
- fn normalize_with_cause<T>(&mut self, value: T, cause: ObligationCause<'tcx>) -> T
- where
- T: TypeFoldable<'tcx>,
- {
- self.infcx
- .partially_normalize_associated_types_in(cause, self.param_env, value)
- .into_value_registering_obligations(self.infcx, self.fulfill_cx)
- }
+ // Prove the predicates coming along with `def_id`.
+ //
+ // Also, normalize the `instantiated_predicates`
+ // because otherwise we wind up with duplicate "type
+ // outlives" error messages.
+ let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs);
- fn relate<T>(&mut self, a: T, variance: Variance, b: T) -> Result<(), NoSolution>
- where
- T: ToTrace<'tcx>,
+ debug!(?instantiated_predicates);
+ for (instantiated_predicate, predicate_span) in
+ zip(instantiated_predicates.predicates, instantiated_predicates.spans)
{
- self.infcx
- .at(&ObligationCause::dummy_with_span(self.span), self.param_env)
- .relate(a, variance, b)?
- .into_value_registering_obligations(self.infcx, self.fulfill_cx);
- Ok(())
- }
-
- fn prove_predicate(&mut self, predicate: Predicate<'tcx>, cause: ObligationCause<'tcx>) {
- self.fulfill_cx.register_predicate_obligation(
- self.infcx,
- Obligation::new(cause, self.param_env, predicate),
+ let span = if span == DUMMY_SP { predicate_span } else { span };
+ let cause = ObligationCause::new(
+ span,
+ hir::CRATE_HIR_ID,
+ ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
);
- }
+ let instantiated_predicate =
+ ocx.normalize(&cause.clone(), param_env, instantiated_predicate);
- fn tcx(&self) -> TyCtxt<'tcx> {
- self.infcx.tcx
+ ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate));
}
- fn subst<T>(&self, value: T, substs: &[GenericArg<'tcx>]) -> T
- where
- T: TypeFoldable<'tcx>,
- {
- EarlyBinder(value).subst(self.tcx(), substs)
- }
+ if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
+ let impl_self_ty = tcx.bound_type_of(impl_def_id).subst(tcx, substs);
+ let impl_self_ty = ocx.normalize(&cause, param_env, impl_self_ty);
- #[instrument(level = "debug", skip(self))]
- fn relate_mir_and_user_ty(
- &mut self,
- mir_ty: Ty<'tcx>,
- def_id: DefId,
- user_substs: UserSubsts<'tcx>,
- ) -> Result<(), NoSolution> {
- let UserSubsts { user_self_ty, substs } = user_substs;
- let tcx = self.tcx();
+ ocx.eq(&cause, param_env, self_ty, impl_self_ty)?;
- let ty = tcx.type_of(def_id);
- let ty = self.subst(ty, substs);
- let ty = self.normalize(ty);
- debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
-
- self.relate(mir_ty, Variance::Invariant, ty)?;
-
- // Prove the predicates coming along with `def_id`.
- //
- // Also, normalize the `instantiated_predicates`
- // because otherwise we wind up with duplicate "type
- // outlives" error messages.
- let instantiated_predicates =
- self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs);
-
- let cause = ObligationCause::dummy_with_span(self.span);
-
- debug!(?instantiated_predicates);
- for (instantiated_predicate, predicate_span) in
- zip(instantiated_predicates.predicates, instantiated_predicates.spans)
- {
- let span = if self.span == DUMMY_SP { predicate_span } else { self.span };
- let cause = ObligationCause::new(
- span,
- hir::CRATE_HIR_ID,
- ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span),
- );
- let instantiated_predicate =
- self.normalize_with_cause(instantiated_predicate, cause.clone());
- self.prove_predicate(instantiated_predicate, cause);
- }
-
- if let Some(UserSelfTy { impl_def_id, self_ty }) = user_self_ty {
- let impl_self_ty = self.tcx().type_of(impl_def_id);
- let impl_self_ty = self.subst(impl_self_ty, &substs);
- let impl_self_ty = self.normalize(impl_self_ty);
-
- self.relate(self_ty, Variance::Invariant, impl_self_ty)?;
-
- self.prove_predicate(
- ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into()))
- .to_predicate(self.tcx()),
- cause.clone(),
- );
- }
-
- // In addition to proving the predicates, we have to
- // prove that `ty` is well-formed -- this is because
- // the WF of `ty` is predicated on the substs being
- // well-formed, and we haven't proven *that*. We don't
- // want to prove the WF of types from `substs` directly because they
- // haven't been normalized.
- //
- // FIXME(nmatsakis): Well, perhaps we should normalize
- // them? This would only be relevant if some input
- // type were ill-formed but did not appear in `ty`,
- // which...could happen with normalization...
- self.prove_predicate(
- ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(self.tcx()),
- cause,
- );
- Ok(())
+ let predicate: Predicate<'tcx> =
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(impl_self_ty.into())).to_predicate(tcx);
+ ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
}
+
+ // In addition to proving the predicates, we have to
+ // prove that `ty` is well-formed -- this is because
+ // the WF of `ty` is predicated on the substs being
+ // well-formed, and we haven't proven *that*. We don't
+ // want to prove the WF of types from `substs` directly because they
+ // haven't been normalized.
+ //
+ // FIXME(nmatsakis): Well, perhaps we should normalize
+ // them? This would only be relevant if some input
+ // type were ill-formed but did not appear in `ty`,
+ // which...could happen with normalization...
+ let predicate: Predicate<'tcx> =
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())).to_predicate(tcx);
+ ocx.register_obligation(Obligation::new(tcx, cause, param_env, predicate));
+ Ok(())
}
fn type_op_eq<'tcx>(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>,
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
- tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
+ tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| {
let (param_env, Eq { a, b }) = key.into_parts();
- infcx
- .at(&ObligationCause::dummy(), param_env)
- .eq(a, b)?
- .into_value_registering_obligations(infcx, fulfill_cx);
- Ok(())
+ Ok(ocx.eq(&ObligationCause::dummy(), param_env, a, b)?)
})
}
fn type_op_normalize<'tcx, T>(
- infcx: &InferCtxt<'tcx>,
- fulfill_cx: &mut dyn TraitEngine<'tcx>,
+ ocx: &ObligationCtxt<'_, 'tcx>,
key: ParamEnvAnd<'tcx, Normalize<T>>,
) -> Fallible<T>
where
@@ -219,8 +137,8 @@ where
{
let (param_env, Normalize { value }) = key.into_parts();
let Normalized { value, obligations } =
- infcx.at(&ObligationCause::dummy(), param_env).normalize(value)?;
- fulfill_cx.register_predicate_obligations(infcx, obligations);
+ ocx.infcx.at(&ObligationCause::dummy(), param_env).query_normalize(value)?;
+ ocx.register_obligations(obligations);
Ok(value)
}
@@ -256,13 +174,9 @@ fn type_op_subtype<'tcx>(
tcx: TyCtxt<'tcx>,
canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Subtype<'tcx>>>,
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
- tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| {
+ tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| {
let (param_env, Subtype { sub, sup }) = key.into_parts();
- infcx
- .at(&ObligationCause::dummy(), param_env)
- .sup(sup, sub)?
- .into_value_registering_obligations(infcx, fulfill_cx);
- Ok(())
+ Ok(ocx.sup(&ObligationCause::dummy(), param_env, sup, sub)?)
})
}
@@ -274,8 +188,8 @@ fn type_op_prove_predicate<'tcx>(
// impl-trait/issue-99642.rs
tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).enter_canonical_trait_query(
&canonicalized,
- |infcx, fulfill_cx, key| {
- type_op_prove_predicate_with_cause(infcx, fulfill_cx, key, ObligationCause::dummy());
+ |ocx, key| {
+ type_op_prove_predicate_with_cause(ocx, key, ObligationCause::dummy());
Ok(())
},
)
@@ -284,12 +198,11 @@ fn type_op_prove_predicate<'tcx>(
/// The core of the `type_op_prove_predicate` query: for diagnostics purposes in NLL HRTB errors,
/// this query can be re-run to better track the span of the obligation cause, and improve the error
/// message. Do not call directly unless you're in that very specific context.
-pub fn type_op_prove_predicate_with_cause<'a, 'tcx: 'a>(
- infcx: &'a InferCtxt<'tcx>,
- fulfill_cx: &'a mut dyn TraitEngine<'tcx>,
+pub fn type_op_prove_predicate_with_cause<'tcx>(
+ ocx: &ObligationCtxt<'_, 'tcx>,
key: ParamEnvAnd<'tcx, ProvePredicate<'tcx>>,
cause: ObligationCause<'tcx>,
) {
let (param_env, ProvePredicate { predicate }) = key.into_parts();
- fulfill_cx.register_predicate_obligation(infcx, Obligation::new(cause, param_env, predicate));
+ ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate));
}