Use BoundVarsCollector
for now
This commit is contained in:
parent
242ac57015
commit
13e116f1f7
@ -7,7 +7,7 @@
|
|||||||
use crate::ty::query::TyCtxtAt;
|
use crate::ty::query::TyCtxtAt;
|
||||||
use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
|
use crate::ty::subst::{GenericArgKind, Subst, SubstsRef};
|
||||||
use crate::ty::TyKind::*;
|
use crate::ty::TyKind::*;
|
||||||
use crate::ty::{self, DefIdTree, List, Ty, TyCtxt, TypeFoldable};
|
use crate::ty::{self, DebruijnIndex, DefIdTree, List, Ty, TyCtxt, TypeFoldable};
|
||||||
use rustc_apfloat::Float as _;
|
use rustc_apfloat::Float as _;
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_attr::{self as attr, SignedInt, UnsignedInt};
|
use rustc_attr::{self as attr, SignedInt, UnsignedInt};
|
||||||
@ -905,6 +905,10 @@ pub fn peel_refs(&'tcx self) -> Ty<'tcx> {
|
|||||||
}
|
}
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn outer_exclusive_binder(&'tcx self) -> DebruijnIndex {
|
||||||
|
self.outer_exclusive_binder
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ExplicitSelf<'tcx> {
|
pub enum ExplicitSelf<'tcx> {
|
||||||
|
@ -2,14 +2,98 @@
|
|||||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||||
use rustc_infer::infer::TyCtxtInferExt;
|
use rustc_infer::infer::TyCtxtInferExt;
|
||||||
use rustc_middle::ty::subst::SubstsRef;
|
use rustc_middle::ty::subst::SubstsRef;
|
||||||
use rustc_middle::ty::{self, Instance, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, Binder, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitor};
|
||||||
use rustc_span::{sym, DUMMY_SP};
|
use rustc_span::{sym, DUMMY_SP};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
use traits::{translate_substs, Reveal};
|
use traits::{translate_substs, Reveal};
|
||||||
|
|
||||||
|
use rustc_data_structures::sso::SsoHashSet;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
|
// FIXME(#86795): `BoundVarsCollector` here should **NOT** be used
|
||||||
|
// outside of `resolve_associated_item`. It's just to address #64494,
|
||||||
|
// #83765, and #85848 which are creating bound types/regions that lose
|
||||||
|
// their `Binder` *unintentionally*.
|
||||||
|
// It's ideal to remove `BoundVarsCollector` and just use
|
||||||
|
// `ty::Binder::*` methods but we use this stopgap until we figure out
|
||||||
|
// the "real" fix.
|
||||||
|
struct BoundVarsCollector<'tcx> {
|
||||||
|
binder_index: ty::DebruijnIndex,
|
||||||
|
vars: BTreeMap<u32, ty::BoundVariableKind>,
|
||||||
|
// We may encounter the same variable at different levels of binding, so
|
||||||
|
// this can't just be `Ty`
|
||||||
|
visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> BoundVarsCollector<'tcx> {
|
||||||
|
fn new() -> Self {
|
||||||
|
BoundVarsCollector {
|
||||||
|
binder_index: ty::INNERMOST,
|
||||||
|
vars: BTreeMap::new(),
|
||||||
|
visited: SsoHashSet::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List<ty::BoundVariableKind> {
|
||||||
|
let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or_else(|| 0);
|
||||||
|
for i in 0..max {
|
||||||
|
if let None = self.vars.get(&i) {
|
||||||
|
panic!("Unknown variable: {:?}", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tcx.mk_bound_variable_kinds(self.vars.into_iter().map(|(_, v)| v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
|
||||||
|
type BreakTy = ();
|
||||||
|
|
||||||
|
fn visit_binder<T: TypeFoldable<'tcx>>(
|
||||||
|
&mut self,
|
||||||
|
t: &Binder<'tcx, T>,
|
||||||
|
) -> ControlFlow<Self::BreakTy> {
|
||||||
|
self.binder_index.shift_in(1);
|
||||||
|
let result = t.super_visit_with(self);
|
||||||
|
self.binder_index.shift_out(1);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
|
if t.outer_exclusive_binder() < self.binder_index
|
||||||
|
|| !self.visited.insert((self.binder_index, t))
|
||||||
|
{
|
||||||
|
return ControlFlow::CONTINUE;
|
||||||
|
}
|
||||||
|
use std::collections::btree_map::Entry;
|
||||||
|
match *t.kind() {
|
||||||
|
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
|
||||||
|
match self.vars.entry(bound_ty.var.as_u32()) {
|
||||||
|
Entry::Vacant(entry) => {
|
||||||
|
entry.insert(ty::BoundVariableKind::Ty(bound_ty.kind));
|
||||||
|
}
|
||||||
|
Entry::Occupied(entry) => match entry.get() {
|
||||||
|
ty::BoundVariableKind::Ty(_) => {}
|
||||||
|
_ => bug!("Conflicting bound vars"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
t.super_visit_with(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||||
|
r.super_visit_with(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(tcx))]
|
#[instrument(level = "debug", skip(tcx))]
|
||||||
fn resolve_instance<'tcx>(
|
fn resolve_instance<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
@ -115,14 +199,12 @@ fn resolve_associated_item<'tcx>(
|
|||||||
);
|
);
|
||||||
|
|
||||||
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
|
||||||
let vtbl = if trait_item.kind == ty::AssocKind::Const {
|
|
||||||
let bound_vars = tcx
|
// See FIXME on `BoundVarsCollector`.
|
||||||
.mk_bound_variable_kinds(std::iter::once(ty::BoundVariableKind::Region(ty::BrAnon(0))));
|
let mut bound_vars_collector = BoundVarsCollector::new();
|
||||||
let bind = ty::Binder::bind_with_vars(trait_ref, bound_vars);
|
trait_ref.visit_with(&mut bound_vars_collector);
|
||||||
tcx.codegen_fulfill_obligation((param_env, bind))?
|
let trait_binder = ty::Binder::bind_with_vars(trait_ref, bound_vars_collector.into_vars(tcx));
|
||||||
} else {
|
let vtbl = tcx.codegen_fulfill_obligation((param_env, trait_binder))?;
|
||||||
tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref, tcx)))?
|
|
||||||
};
|
|
||||||
|
|
||||||
// Now that we know which impl is being used, we can dispatch to
|
// Now that we know which impl is being used, we can dispatch to
|
||||||
// the actual function:
|
// the actual function:
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
//! This API is completely unstable and subject to change.
|
//! This API is completely unstable and subject to change.
|
||||||
|
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
|
#![feature(control_flow_enum)]
|
||||||
#![feature(half_open_range_patterns)]
|
#![feature(half_open_range_patterns)]
|
||||||
#![feature(exclusive_range_pattern)]
|
#![feature(exclusive_range_pattern)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
|
Loading…
Reference in New Issue
Block a user