1
Fork 0

Auto merge of #86866 - nikomatsakis:issue-84841, r=oli-obk

Hack: Ignore inference variables in certain queries

Fixes #84841
Fixes #86753

Some queries are not built to accept types with inference variables, which can lead to ICEs. These queries probably ought to be converted to canonical form, but as a quick workaround, we can return conservative results in the case that inference variables are found.

We should file a follow-up issue (and update the FIXMEs...) to do the proper refactoring.

cc `@arora-aman`

r? `@oli-obk`
This commit is contained in:
bors 2021-07-04 17:39:37 +00:00
commit 23c652dfe3
13 changed files with 168 additions and 58 deletions

View file

@ -1559,9 +1559,22 @@ rustc_queries! {
desc { "evaluating trait selection obligation `{}`", goal.value }
}
/// Evaluates whether the given type implements the given trait
/// in the given environment.
///
/// The inputs are:
///
/// - the def-id of the trait
/// - the self type
/// - the *other* type parameters of the trait, excluding the self-type
/// - the parameter environment
///
/// FIXME. If the type, trait, or environment has inference variables,
/// this yields `EvaluatedToUnknown`. It should be refactored
/// to use canonicalization, really.
query type_implements_trait(
key: (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>, )
) -> bool {
) -> traits::EvaluationResult {
desc { "evaluating `type_implements_trait` `{:?}`", key }
}

View file

@ -88,23 +88,32 @@ struct NormalizeAfterErasingRegionsFolder<'tcx> {
param_env: ty::ParamEnv<'tcx>,
}
impl<'tcx> NormalizeAfterErasingRegionsFolder<'tcx> {
fn normalize_generic_arg_after_erasing_regions(
&self,
arg: ty::GenericArg<'tcx>,
) -> ty::GenericArg<'tcx> {
let arg = self.param_env.and(arg);
self.tcx.normalize_generic_arg_after_erasing_regions(arg)
}
}
impl TypeFolder<'tcx> for NormalizeAfterErasingRegionsFolder<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
let arg = self.param_env.and(ty.into());
self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_ty()
self.normalize_generic_arg_after_erasing_regions(ty.into()).expect_ty()
}
fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
let arg = self.param_env.and(c.into());
self.tcx.normalize_generic_arg_after_erasing_regions(arg).expect_const()
self.normalize_generic_arg_after_erasing_regions(c.into()).expect_const()
}
#[inline]
fn fold_mir_const(&mut self, c: mir::ConstantKind<'tcx>) -> mir::ConstantKind<'tcx> {
// FIXME: This *probably* needs canonicalization too!
let arg = self.param_env.and(c);
self.tcx.normalize_mir_const_after_erasing_regions(arg)
}

View file

@ -816,6 +816,15 @@ impl<'tcx> ty::TyS<'tcx> {
[component_ty] => component_ty,
_ => self,
};
// FIXME(#86868): We should be canonicalizing, or else moving this to a method of inference
// context, or *something* like that, but for now just avoid passing inference
// variables to queries that can't cope with them. Instead, conservatively
// return "true" (may change drop order).
if query_ty.needs_infer() {
return true;
}
// This doesn't depend on regions, so try to minimize distinct
// query keys used.
let erased = tcx.normalize_erasing_regions(param_env, query_ty);