mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 11:07:42 +00:00
Rollup merge of #111246 - lcnr:no-escaping-bound-vars, r=compiler-errors
forbid escaping bound vars in combine removes the `CollectAllMismatches` in favor of a slightly more manual approach. r? types cc ``@estebank``
This commit is contained in:
commit
ce71f570f4
@ -73,6 +73,8 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
R: ObligationEmittingRelation<'tcx>,
|
R: ObligationEmittingRelation<'tcx>,
|
||||||
{
|
{
|
||||||
let a_is_expected = relation.a_is_expected();
|
let a_is_expected = relation.a_is_expected();
|
||||||
|
debug_assert!(!a.has_escaping_bound_vars());
|
||||||
|
debug_assert!(!b.has_escaping_bound_vars());
|
||||||
|
|
||||||
match (a.kind(), b.kind()) {
|
match (a.kind(), b.kind()) {
|
||||||
// Relate integral variables to other types
|
// Relate integral variables to other types
|
||||||
@ -163,6 +165,8 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
R: ObligationEmittingRelation<'tcx>,
|
R: ObligationEmittingRelation<'tcx>,
|
||||||
{
|
{
|
||||||
debug!("{}.consts({:?}, {:?})", relation.tag(), a, b);
|
debug!("{}.consts({:?}, {:?})", relation.tag(), a, b);
|
||||||
|
debug_assert!(!a.has_escaping_bound_vars());
|
||||||
|
debug_assert!(!b.has_escaping_bound_vars());
|
||||||
if a == b {
|
if a == b {
|
||||||
return Ok(a);
|
return Ok(a);
|
||||||
}
|
}
|
||||||
@ -238,22 +242,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||||||
(_, ty::ConstKind::Infer(InferConst::Var(vid))) => {
|
(_, ty::ConstKind::Infer(InferConst::Var(vid))) => {
|
||||||
return self.unify_const_variable(vid, a);
|
return self.unify_const_variable(vid, a);
|
||||||
}
|
}
|
||||||
(ty::ConstKind::Unevaluated(..), _) if self.tcx.lazy_normalization() => {
|
(ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..))
|
||||||
// FIXME(#59490): Need to remove the leak check to accommodate
|
if self.tcx.lazy_normalization() =>
|
||||||
// escaping bound variables here.
|
{
|
||||||
if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
|
relation.register_const_equate_obligation(a, b);
|
||||||
relation.register_const_equate_obligation(a, b);
|
|
||||||
}
|
|
||||||
return Ok(b);
|
return Ok(b);
|
||||||
}
|
}
|
||||||
(_, ty::ConstKind::Unevaluated(..)) if self.tcx.lazy_normalization() => {
|
|
||||||
// FIXME(#59490): Need to remove the leak check to accommodate
|
|
||||||
// escaping bound variables here.
|
|
||||||
if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
|
|
||||||
relation.register_const_equate_obligation(a, b);
|
|
||||||
}
|
|
||||||
return Ok(a);
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,102 +0,0 @@
|
|||||||
use crate::infer::InferCtxt;
|
|
||||||
|
|
||||||
use rustc_infer::infer::ObligationEmittingRelation;
|
|
||||||
use rustc_infer::traits::PredicateObligations;
|
|
||||||
use rustc_middle::ty::error::TypeError;
|
|
||||||
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
|
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
|
||||||
|
|
||||||
pub struct CollectAllMismatches<'a, 'tcx> {
|
|
||||||
pub infcx: &'a InferCtxt<'tcx>,
|
|
||||||
pub param_env: ty::ParamEnv<'tcx>,
|
|
||||||
pub errors: Vec<TypeError<'tcx>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'tcx> TypeRelation<'tcx> for CollectAllMismatches<'a, 'tcx> {
|
|
||||||
fn tag(&self) -> &'static str {
|
|
||||||
"CollectAllMismatches"
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
|
||||||
self.infcx.tcx
|
|
||||||
}
|
|
||||||
|
|
||||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
|
||||||
self.param_env
|
|
||||||
}
|
|
||||||
|
|
||||||
fn a_is_expected(&self) -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn relate_with_variance<T: Relate<'tcx>>(
|
|
||||||
&mut self,
|
|
||||||
_: ty::Variance,
|
|
||||||
_: ty::VarianceDiagInfo<'tcx>,
|
|
||||||
a: T,
|
|
||||||
b: T,
|
|
||||||
) -> RelateResult<'tcx, T> {
|
|
||||||
self.relate(a, b)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn regions(
|
|
||||||
&mut self,
|
|
||||||
a: ty::Region<'tcx>,
|
|
||||||
_b: ty::Region<'tcx>,
|
|
||||||
) -> RelateResult<'tcx, ty::Region<'tcx>> {
|
|
||||||
Ok(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
|
||||||
self.infcx.probe(|_| {
|
|
||||||
if a.is_ty_var() || b.is_ty_var() {
|
|
||||||
Ok(a)
|
|
||||||
} else {
|
|
||||||
self.infcx.super_combine_tys(self, a, b).or_else(|e| {
|
|
||||||
self.errors.push(e);
|
|
||||||
Ok(a)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn consts(
|
|
||||||
&mut self,
|
|
||||||
a: ty::Const<'tcx>,
|
|
||||||
b: ty::Const<'tcx>,
|
|
||||||
) -> RelateResult<'tcx, ty::Const<'tcx>> {
|
|
||||||
self.infcx.probe(|_| {
|
|
||||||
if a.is_ct_infer() || b.is_ct_infer() {
|
|
||||||
Ok(a)
|
|
||||||
} else {
|
|
||||||
relate::super_relate_consts(self, a, b) // could do something similar here for constants!
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn binders<T: Relate<'tcx>>(
|
|
||||||
&mut self,
|
|
||||||
a: ty::Binder<'tcx, T>,
|
|
||||||
b: ty::Binder<'tcx, T>,
|
|
||||||
) -> RelateResult<'tcx, ty::Binder<'tcx, T>> {
|
|
||||||
Ok(a.rebind(self.relate(a.skip_binder(), b.skip_binder())?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> ObligationEmittingRelation<'tcx> for CollectAllMismatches<'_, 'tcx> {
|
|
||||||
fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
|
|
||||||
// FIXME(deferred_projection_equality): We really should get rid of this relation.
|
|
||||||
ty::AliasRelationDirection::Equate
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register_obligations(&mut self, _obligations: PredicateObligations<'tcx>) {
|
|
||||||
// FIXME(deferred_projection_equality)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register_predicates(
|
|
||||||
&mut self,
|
|
||||||
_obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>,
|
|
||||||
) {
|
|
||||||
// FIXME(deferred_projection_equality)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,4 @@
|
|||||||
mod ambiguity;
|
mod ambiguity;
|
||||||
pub mod method_chain;
|
|
||||||
pub mod on_unimplemented;
|
pub mod on_unimplemented;
|
||||||
pub mod suggestions;
|
pub mod suggestions;
|
||||||
|
|
||||||
@ -559,6 +558,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
suggest_increasing_limit,
|
suggest_increasing_limit,
|
||||||
|err| {
|
|err| {
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
|
obligation.cause.body_id,
|
||||||
err,
|
err,
|
||||||
predicate,
|
predicate,
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
@ -1431,6 +1431,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
| ObligationCauseCode::ExprItemObligation(..) = code
|
| ObligationCauseCode::ExprItemObligation(..) = code
|
||||||
{
|
{
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
|
error.obligation.cause.body_id,
|
||||||
&mut diag,
|
&mut diag,
|
||||||
error.obligation.predicate,
|
error.obligation.predicate,
|
||||||
error.obligation.param_env,
|
error.obligation.param_env,
|
||||||
@ -2544,6 +2545,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
// message, and fall back to regular note otherwise.
|
// message, and fall back to regular note otherwise.
|
||||||
if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
|
if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
|
obligation.cause.body_id,
|
||||||
err,
|
err,
|
||||||
obligation.predicate,
|
obligation.predicate,
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
|
@ -25,10 +25,9 @@ use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node};
|
|||||||
use rustc_hir::{Expr, HirId};
|
use rustc_hir::{Expr, HirId};
|
||||||
use rustc_infer::infer::error_reporting::TypeErrCtxt;
|
use rustc_infer::infer::error_reporting::TypeErrCtxt;
|
||||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||||
use rustc_infer::infer::{InferOk, LateBoundRegionConversionTime};
|
use rustc_infer::infer::{DefineOpaqueTypes, InferOk, LateBoundRegionConversionTime};
|
||||||
use rustc_middle::hir::map;
|
use rustc_middle::hir::map;
|
||||||
use rustc_middle::ty::error::TypeError::{self, Sorts};
|
use rustc_middle::ty::error::TypeError::{self, Sorts};
|
||||||
use rustc_middle::ty::relate::TypeRelation;
|
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind,
|
self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind,
|
||||||
GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts,
|
GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, InternalSubsts,
|
||||||
@ -39,9 +38,9 @@ use rustc_span::def_id::LocalDefId;
|
|||||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||||
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
|
use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span, DUMMY_SP};
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
|
use std::iter;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use super::method_chain::CollectAllMismatches;
|
|
||||||
use super::InferCtxtPrivExt;
|
use super::InferCtxtPrivExt;
|
||||||
use crate::infer::InferCtxtExt as _;
|
use crate::infer::InferCtxtExt as _;
|
||||||
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||||
@ -319,6 +318,7 @@ pub trait TypeErrCtxtExt<'tcx> {
|
|||||||
|
|
||||||
fn note_obligation_cause_code<T>(
|
fn note_obligation_cause_code<T>(
|
||||||
&self,
|
&self,
|
||||||
|
body_id: LocalDefId,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
predicate: T,
|
predicate: T,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
@ -359,8 +359,9 @@ pub trait TypeErrCtxtExt<'tcx> {
|
|||||||
);
|
);
|
||||||
fn note_function_argument_obligation(
|
fn note_function_argument_obligation(
|
||||||
&self,
|
&self,
|
||||||
arg_hir_id: HirId,
|
body_id: LocalDefId,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
|
arg_hir_id: HirId,
|
||||||
parent_code: &ObligationCauseCode<'tcx>,
|
parent_code: &ObligationCauseCode<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
predicate: ty::Predicate<'tcx>,
|
predicate: ty::Predicate<'tcx>,
|
||||||
@ -2742,6 +2743,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
// bound that introduced the obligation (e.g. `T: Send`).
|
// bound that introduced the obligation (e.g. `T: Send`).
|
||||||
debug!(?next_code);
|
debug!(?next_code);
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
|
obligation.cause.body_id,
|
||||||
err,
|
err,
|
||||||
obligation.predicate,
|
obligation.predicate,
|
||||||
obligation.param_env,
|
obligation.param_env,
|
||||||
@ -2753,6 +2755,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
|
|
||||||
fn note_obligation_cause_code<T>(
|
fn note_obligation_cause_code<T>(
|
||||||
&self,
|
&self,
|
||||||
|
body_id: LocalDefId,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
predicate: T,
|
predicate: T,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
@ -3152,6 +3155,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
// #74711: avoid a stack overflow
|
// #74711: avoid a stack overflow
|
||||||
ensure_sufficient_stack(|| {
|
ensure_sufficient_stack(|| {
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
|
body_id,
|
||||||
err,
|
err,
|
||||||
parent_predicate,
|
parent_predicate,
|
||||||
param_env,
|
param_env,
|
||||||
@ -3163,6 +3167,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
ensure_sufficient_stack(|| {
|
ensure_sufficient_stack(|| {
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
|
body_id,
|
||||||
err,
|
err,
|
||||||
parent_predicate,
|
parent_predicate,
|
||||||
param_env,
|
param_env,
|
||||||
@ -3292,6 +3297,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
// #74711: avoid a stack overflow
|
// #74711: avoid a stack overflow
|
||||||
ensure_sufficient_stack(|| {
|
ensure_sufficient_stack(|| {
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
|
body_id,
|
||||||
err,
|
err,
|
||||||
parent_predicate,
|
parent_predicate,
|
||||||
param_env,
|
param_env,
|
||||||
@ -3307,6 +3313,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
// #74711: avoid a stack overflow
|
// #74711: avoid a stack overflow
|
||||||
ensure_sufficient_stack(|| {
|
ensure_sufficient_stack(|| {
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
|
body_id,
|
||||||
err,
|
err,
|
||||||
parent_predicate,
|
parent_predicate,
|
||||||
param_env,
|
param_env,
|
||||||
@ -3323,8 +3330,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
self.note_function_argument_obligation(
|
self.note_function_argument_obligation(
|
||||||
arg_hir_id,
|
body_id,
|
||||||
err,
|
err,
|
||||||
|
arg_hir_id,
|
||||||
parent_code,
|
parent_code,
|
||||||
param_env,
|
param_env,
|
||||||
predicate,
|
predicate,
|
||||||
@ -3332,6 +3340,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
);
|
);
|
||||||
ensure_sufficient_stack(|| {
|
ensure_sufficient_stack(|| {
|
||||||
self.note_obligation_cause_code(
|
self.note_obligation_cause_code(
|
||||||
|
body_id,
|
||||||
err,
|
err,
|
||||||
predicate,
|
predicate,
|
||||||
param_env,
|
param_env,
|
||||||
@ -3553,8 +3562,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
fn note_function_argument_obligation(
|
fn note_function_argument_obligation(
|
||||||
&self,
|
&self,
|
||||||
arg_hir_id: HirId,
|
body_id: LocalDefId,
|
||||||
err: &mut Diagnostic,
|
err: &mut Diagnostic,
|
||||||
|
arg_hir_id: HirId,
|
||||||
parent_code: &ObligationCauseCode<'tcx>,
|
parent_code: &ObligationCauseCode<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
failed_pred: ty::Predicate<'tcx>,
|
failed_pred: ty::Predicate<'tcx>,
|
||||||
@ -3587,7 +3597,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
// to an associated type (as seen from `trait_pred`) in the predicate. Like in
|
// to an associated type (as seen from `trait_pred`) in the predicate. Like in
|
||||||
// trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
|
// trait_pred `S: Sum<<Self as Iterator>::Item>` and predicate `i32: Sum<&()>`
|
||||||
let mut type_diffs = vec![];
|
let mut type_diffs = vec![];
|
||||||
|
|
||||||
if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
|
if let ObligationCauseCode::ExprBindingObligation(def_id, _, _, idx) = parent_code.deref()
|
||||||
&& let Some(node_substs) = typeck_results.node_substs_opt(call_hir_id)
|
&& let Some(node_substs) = typeck_results.node_substs_opt(call_hir_id)
|
||||||
&& let where_clauses = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_substs)
|
&& let where_clauses = self.tcx.predicates_of(def_id).instantiate(self.tcx, node_substs)
|
||||||
@ -3596,14 +3605,26 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
|||||||
if let Some(where_pred) = where_pred.to_opt_poly_trait_pred()
|
if let Some(where_pred) = where_pred.to_opt_poly_trait_pred()
|
||||||
&& let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred()
|
&& let Some(failed_pred) = failed_pred.to_opt_poly_trait_pred()
|
||||||
{
|
{
|
||||||
let mut c = CollectAllMismatches {
|
let where_pred = self.instantiate_binder_with_placeholders(where_pred);
|
||||||
infcx: self.infcx,
|
let failed_pred = self.instantiate_binder_with_fresh_vars(
|
||||||
param_env,
|
expr.span,
|
||||||
errors: vec![],
|
LateBoundRegionConversionTime::FnCall,
|
||||||
|
failed_pred
|
||||||
|
);
|
||||||
|
|
||||||
|
let zipped =
|
||||||
|
iter::zip(where_pred.trait_ref.substs, failed_pred.trait_ref.substs);
|
||||||
|
for (expected, actual) in zipped {
|
||||||
|
self.probe(|_| {
|
||||||
|
match self
|
||||||
|
.at(&ObligationCause::misc(expr.span, body_id), param_env)
|
||||||
|
.eq(DefineOpaqueTypes::No, expected, actual)
|
||||||
|
{
|
||||||
|
Ok(_) => (), // We ignore nested obligations here for now.
|
||||||
|
Err(err) => type_diffs.push(err),
|
||||||
|
}
|
||||||
|
})
|
||||||
};
|
};
|
||||||
if let Ok(_) = c.relate(where_pred, failed_pred) {
|
|
||||||
type_diffs = c.errors;
|
|
||||||
}
|
|
||||||
} else if let Some(where_pred) = where_pred.to_opt_poly_projection_pred()
|
} else if let Some(where_pred) = where_pred.to_opt_poly_projection_pred()
|
||||||
&& let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred()
|
&& let Some(failed_pred) = failed_pred.to_opt_poly_projection_pred()
|
||||||
&& let Some(found) = failed_pred.skip_binder().term.ty()
|
&& let Some(found) = failed_pred.skip_binder().term.ty()
|
||||||
|
Loading…
Reference in New Issue
Block a user