Auto merge of #86795 - JohnTitor:fix-bind, r=jackh726
Fix const-generics ICE related to binding Fixes #83765, fixes #85848 r? `@jackh726` as you're familiar with `Binding`. I'd like to get some views if the current approach is right path.
This commit is contained in:
commit
cd48e61c5d
17 changed files with 280 additions and 125 deletions
|
@ -754,88 +754,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub 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> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
BoundVarsCollector {
|
|
||||||
binder_index: ty::INNERMOST,
|
|
||||||
vars: BTreeMap::new(),
|
|
||||||
visited: SsoHashSet::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub 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> {
|
|
||||||
match r {
|
|
||||||
ty::ReLateBound(index, _br) if *index == self.binder_index => {
|
|
||||||
// If you hit this, you should be using `Binder::bind_with_vars` or `Binder::rebind`
|
|
||||||
bug!("Trying to collect bound vars with a bound region: {:?} {:?}", index, _br)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => (),
|
|
||||||
};
|
|
||||||
|
|
||||||
r.super_visit_with(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ValidateBoundVars<'tcx> {
|
pub struct ValidateBoundVars<'tcx> {
|
||||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||||
binder_index: ty::DebruijnIndex,
|
binder_index: ty::DebruijnIndex,
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
use self::TyKind::*;
|
use self::TyKind::*;
|
||||||
|
|
||||||
use crate::infer::canonical::Canonical;
|
use crate::infer::canonical::Canonical;
|
||||||
use crate::ty::fold::BoundVarsCollector;
|
|
||||||
use crate::ty::fold::ValidateBoundVars;
|
use crate::ty::fold::ValidateBoundVars;
|
||||||
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
|
use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
|
||||||
use crate::ty::InferTy::{self, *};
|
use crate::ty::InferTy::{self, *};
|
||||||
|
@ -970,13 +969,6 @@ where
|
||||||
Binder(value, ty::List::empty())
|
Binder(value, ty::List::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wraps `value` in a binder, binding higher-ranked vars (if any).
|
|
||||||
pub fn bind(value: T, tcx: TyCtxt<'tcx>) -> Binder<'tcx, T> {
|
|
||||||
let mut collector = BoundVarsCollector::new();
|
|
||||||
value.visit_with(&mut collector);
|
|
||||||
Binder(value, collector.into_vars(tcx))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
|
pub fn bind_with_vars(value: T, vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
let mut validator = ValidateBoundVars::new(vars);
|
let mut validator = ValidateBoundVars::new(vars);
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::ty::layout::IntegerExt;
|
||||||
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 @@ impl<'tcx> ty::TyS<'tcx> {
|
||||||
}
|
}
|
||||||
ty
|
ty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn outer_exclusive_binder(&'tcx self) -> DebruijnIndex {
|
||||||
|
self.outer_exclusive_binder
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum ExplicitSelf<'tcx> {
|
pub enum ExplicitSelf<'tcx> {
|
||||||
|
|
|
@ -822,12 +822,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
|
||||||
let obligation = Obligation::new(
|
let obligation = Obligation::new(
|
||||||
ObligationCause::dummy(),
|
ObligationCause::dummy(),
|
||||||
param_env,
|
param_env,
|
||||||
Binder::bind(
|
Binder::dummy(TraitPredicate { trait_ref }),
|
||||||
TraitPredicate {
|
|
||||||
trait_ref: TraitRef::from_method(tcx, trait_id, substs),
|
|
||||||
},
|
|
||||||
tcx,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let implsrc = tcx.infer_ctxt().enter(|infcx| {
|
let implsrc = tcx.infer_ctxt().enter(|infcx| {
|
||||||
|
|
|
@ -1301,7 +1301,7 @@ fn confirm_pointee_candidate<'cx, 'tcx>(
|
||||||
ty: self_ty.ptr_metadata_ty(tcx),
|
ty: self_ty.ptr_metadata_ty(tcx),
|
||||||
};
|
};
|
||||||
|
|
||||||
confirm_param_env_candidate(selcx, obligation, ty::Binder::bind(predicate, tcx), false)
|
confirm_param_env_candidate(selcx, obligation, ty::Binder::dummy(predicate), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm_fn_pointer_candidate<'cx, 'tcx>(
|
fn confirm_fn_pointer_candidate<'cx, 'tcx>(
|
||||||
|
|
|
@ -2,14 +2,114 @@ use rustc_errors::ErrorReported;
|
||||||
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::btree_map::Entry;
|
||||||
|
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(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;
|
||||||
|
}
|
||||||
|
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> {
|
||||||
|
match r {
|
||||||
|
ty::ReLateBound(index, br) if *index == self.binder_index => {
|
||||||
|
match self.vars.entry(br.var.as_u32()) {
|
||||||
|
Entry::Vacant(entry) => {
|
||||||
|
entry.insert(ty::BoundVariableKind::Region(br.kind));
|
||||||
|
}
|
||||||
|
Entry::Occupied(entry) => match entry.get() {
|
||||||
|
ty::BoundVariableKind::Region(_) => {}
|
||||||
|
_ => bug!("Conflicting bound vars"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
|
||||||
|
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,7 +215,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 = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref, tcx)))?;
|
|
||||||
|
// See FIXME on `BoundVarsCollector`.
|
||||||
|
let mut bound_vars_collector = BoundVarsCollector::new();
|
||||||
|
trait_ref.visit_with(&mut bound_vars_collector);
|
||||||
|
let trait_binder = ty::Binder::bind_with_vars(trait_ref, bound_vars_collector.into_vars(tcx));
|
||||||
|
let vtbl = tcx.codegen_fulfill_obligation((param_env, trait_binder))?;
|
||||||
|
|
||||||
// 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)]
|
||||||
|
|
|
@ -1694,7 +1694,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.one_bound_for_assoc_type(
|
self.one_bound_for_assoc_type(
|
||||||
|| traits::supertraits(tcx, ty::Binder::bind(trait_ref, tcx)),
|
|| traits::supertraits(tcx, ty::Binder::dummy(trait_ref)),
|
||||||
|| "Self".to_string(),
|
|| "Self".to_string(),
|
||||||
assoc_ident,
|
assoc_ident,
|
||||||
span,
|
span,
|
||||||
|
|
|
@ -222,12 +222,7 @@ fn compare_predicate_entailment<'tcx>(
|
||||||
let mut selcx = traits::SelectionContext::new(&infcx);
|
let mut selcx = traits::SelectionContext::new(&infcx);
|
||||||
|
|
||||||
let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
|
let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs);
|
||||||
let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars(
|
for predicate in impl_m_own_bounds.predicates {
|
||||||
impl_m_span,
|
|
||||||
infer::HigherRankedType,
|
|
||||||
ty::Binder::bind(impl_m_own_bounds.predicates, tcx),
|
|
||||||
);
|
|
||||||
for predicate in impl_m_own_bounds {
|
|
||||||
let traits::Normalized { value: predicate, obligations } =
|
let traits::Normalized { value: predicate, obligations } =
|
||||||
traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate);
|
traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate);
|
||||||
|
|
||||||
|
@ -258,14 +253,14 @@ fn compare_predicate_entailment<'tcx>(
|
||||||
);
|
);
|
||||||
let impl_sig =
|
let impl_sig =
|
||||||
inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, impl_sig);
|
inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, impl_sig);
|
||||||
let impl_fty = tcx.mk_fn_ptr(ty::Binder::bind(impl_sig, tcx));
|
let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
|
||||||
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
|
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
|
||||||
|
|
||||||
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id));
|
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id));
|
||||||
let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
|
let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
|
||||||
let trait_sig =
|
let trait_sig =
|
||||||
inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
|
inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
|
||||||
let trait_fty = tcx.mk_fn_ptr(ty::Binder::bind(trait_sig, tcx));
|
let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig));
|
||||||
|
|
||||||
debug!("compare_impl_method: trait_fty={:?}", trait_fty);
|
debug!("compare_impl_method: trait_fty={:?}", trait_fty);
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
|
|
||||||
let (method_sig, method_predicates) =
|
let (method_sig, method_predicates) =
|
||||||
self.normalize_associated_types_in(self.span, (method_sig, method_predicates));
|
self.normalize_associated_types_in(self.span, (method_sig, method_predicates));
|
||||||
|
let method_sig = ty::Binder::dummy(method_sig);
|
||||||
|
|
||||||
// Make sure nobody calls `drop()` explicitly.
|
// Make sure nobody calls `drop()` explicitly.
|
||||||
self.enforce_illegal_method_limitations(&pick);
|
self.enforce_illegal_method_limitations(&pick);
|
||||||
|
@ -119,12 +120,15 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
// We won't add these if we encountered an illegal sized bound, so that we can use
|
// We won't add these if we encountered an illegal sized bound, so that we can use
|
||||||
// a custom error in that case.
|
// a custom error in that case.
|
||||||
if illegal_sized_bound.is_none() {
|
if illegal_sized_bound.is_none() {
|
||||||
let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig, self.tcx));
|
self.add_obligations(self.tcx.mk_fn_ptr(method_sig), all_substs, method_predicates);
|
||||||
self.add_obligations(method_ty, all_substs, method_predicates);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the final `MethodCallee`.
|
// Create the final `MethodCallee`.
|
||||||
let callee = MethodCallee { def_id: pick.item.def_id, substs: all_substs, sig: method_sig };
|
let callee = MethodCallee {
|
||||||
|
def_id: pick.item.def_id,
|
||||||
|
substs: all_substs,
|
||||||
|
sig: method_sig.skip_binder(),
|
||||||
|
};
|
||||||
ConfirmResult { callee, illegal_sized_bound }
|
ConfirmResult { callee, illegal_sized_bound }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds));
|
obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds));
|
||||||
|
|
||||||
// Also add an obligation for the method type being well-formed.
|
// Also add an obligation for the method type being well-formed.
|
||||||
let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig, tcx));
|
let method_ty = tcx.mk_fn_ptr(ty::Binder::dummy(fn_sig));
|
||||||
debug!(
|
debug!(
|
||||||
"lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}",
|
"lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}",
|
||||||
method_ty, obligation
|
method_ty, obligation
|
||||||
|
|
|
@ -1087,14 +1087,9 @@ fn check_method_receiver<'fcx, 'tcx>(
|
||||||
debug!("check_method_receiver: sig={:?}", sig);
|
debug!("check_method_receiver: sig={:?}", sig);
|
||||||
|
|
||||||
let self_ty = fcx.normalize_associated_types_in(span, self_ty);
|
let self_ty = fcx.normalize_associated_types_in(span, self_ty);
|
||||||
let self_ty =
|
|
||||||
fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(self_ty, fcx.tcx));
|
|
||||||
|
|
||||||
let receiver_ty = sig.inputs()[0];
|
let receiver_ty = sig.inputs()[0];
|
||||||
|
|
||||||
let receiver_ty = fcx.normalize_associated_types_in(span, receiver_ty);
|
let receiver_ty = fcx.normalize_associated_types_in(span, receiver_ty);
|
||||||
let receiver_ty =
|
|
||||||
fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::bind(receiver_ty, fcx.tcx));
|
|
||||||
|
|
||||||
if fcx.tcx.features().arbitrary_self_types {
|
if fcx.tcx.features().arbitrary_self_types {
|
||||||
if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
|
if !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) {
|
||||||
|
|
|
@ -1737,11 +1737,12 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
|
||||||
ty::ReErased => tcx.lifetimes.re_static,
|
ty::ReErased => tcx.lifetimes.re_static,
|
||||||
_ => r,
|
_ => r,
|
||||||
});
|
});
|
||||||
|
let fn_sig = ty::Binder::dummy(fn_sig);
|
||||||
|
|
||||||
let mut visitor = PlaceholderHirTyCollector::default();
|
let mut visitor = PlaceholderHirTyCollector::default();
|
||||||
visitor.visit_ty(ty);
|
visitor.visit_ty(ty);
|
||||||
let mut diag = bad_placeholder_type(tcx, visitor.0, "return type");
|
let mut diag = bad_placeholder_type(tcx, visitor.0, "return type");
|
||||||
let ret_ty = fn_sig.output();
|
let ret_ty = fn_sig.skip_binder().output();
|
||||||
if ret_ty != tcx.ty_error() {
|
if ret_ty != tcx.ty_error() {
|
||||||
if !ret_ty.is_closure() {
|
if !ret_ty.is_closure() {
|
||||||
let ret_ty_str = match ret_ty.kind() {
|
let ret_ty_str = match ret_ty.kind() {
|
||||||
|
@ -1767,7 +1768,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
|
||||||
}
|
}
|
||||||
diag.emit();
|
diag.emit();
|
||||||
|
|
||||||
ty::Binder::bind(fn_sig, tcx)
|
fn_sig
|
||||||
}
|
}
|
||||||
None => <dyn AstConv<'_>>::ty_of_fn(
|
None => <dyn AstConv<'_>>::ty_of_fn(
|
||||||
&icx,
|
&icx,
|
||||||
|
@ -1811,10 +1812,13 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> {
|
||||||
let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id).to_def_id());
|
let ty = tcx.type_of(tcx.hir().get_parent_did(hir_id).to_def_id());
|
||||||
let inputs =
|
let inputs =
|
||||||
data.fields().iter().map(|f| tcx.type_of(tcx.hir().local_def_id(f.hir_id)));
|
data.fields().iter().map(|f| tcx.type_of(tcx.hir().local_def_id(f.hir_id)));
|
||||||
ty::Binder::bind(
|
ty::Binder::dummy(tcx.mk_fn_sig(
|
||||||
tcx.mk_fn_sig(inputs, ty, false, hir::Unsafety::Normal, abi::Abi::Rust),
|
inputs,
|
||||||
tcx,
|
ty,
|
||||||
)
|
false,
|
||||||
|
hir::Unsafety::Normal,
|
||||||
|
abi::Abi::Rust,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
|
Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => {
|
||||||
|
@ -2098,7 +2102,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
|
||||||
param.bounds.iter().for_each(|bound| match bound {
|
param.bounds.iter().for_each(|bound| match bound {
|
||||||
hir::GenericBound::Outlives(lt) => {
|
hir::GenericBound::Outlives(lt) => {
|
||||||
let bound = <dyn AstConv<'_>>::ast_region_to_region(&icx, <, None);
|
let bound = <dyn AstConv<'_>>::ast_region_to_region(&icx, <, None);
|
||||||
let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound), tcx);
|
let outlives = ty::Binder::dummy(ty::OutlivesPredicate(region, bound));
|
||||||
predicates.insert((outlives.to_predicate(tcx), lt.span));
|
predicates.insert((outlives.to_predicate(tcx), lt.span));
|
||||||
}
|
}
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
|
|
38
src/test/ui/const-generics/issues/issue-83765.rs
Normal file
38
src/test/ui/const-generics/issues/issue-83765.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#![feature(const_generics, const_evaluatable_checked)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
trait TensorDimension {
|
||||||
|
const DIM: usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait TensorSize: TensorDimension {
|
||||||
|
fn size(&self) -> [usize; Self::DIM];
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Broadcastable: TensorSize + Sized {
|
||||||
|
type Element;
|
||||||
|
fn lazy_updim<const NEWDIM: usize>(&self, size: [usize; NEWDIM]) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BMap<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> {
|
||||||
|
reference: &'a T,
|
||||||
|
closure: F,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorDimension
|
||||||
|
for BMap<'a, R, T, F, DIM>
|
||||||
|
{
|
||||||
|
const DIM: usize = DIM;
|
||||||
|
}
|
||||||
|
impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSize
|
||||||
|
for BMap<'a, R, T, F, DIM>
|
||||||
|
{
|
||||||
|
fn size(&self) -> [usize; DIM] {
|
||||||
|
//~^ ERROR: method not compatible with trait [E0308]
|
||||||
|
self.reference.size()
|
||||||
|
//~^ ERROR: unconstrained generic constant
|
||||||
|
//~| ERROR: mismatched types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
29
src/test/ui/const-generics/issues/issue-83765.stderr
Normal file
29
src/test/ui/const-generics/issues/issue-83765.stderr
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
error[E0308]: method not compatible with trait
|
||||||
|
--> $DIR/issue-83765.rs:30:5
|
||||||
|
|
|
||||||
|
LL | fn size(&self) -> [usize; DIM] {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Self::DIM`, found `DIM`
|
||||||
|
|
|
||||||
|
= note: expected type `Self::DIM`
|
||||||
|
found type `DIM`
|
||||||
|
|
||||||
|
error: unconstrained generic constant
|
||||||
|
--> $DIR/issue-83765.rs:32:24
|
||||||
|
|
|
||||||
|
LL | self.reference.size()
|
||||||
|
| ^^^^
|
||||||
|
|
|
||||||
|
= help: try adding a `where` bound using this expression: `where [(); Self::DIM]:`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/issue-83765.rs:32:9
|
||||||
|
|
|
||||||
|
LL | self.reference.size()
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^ expected `DIM`, found `Self::DIM`
|
||||||
|
|
|
||||||
|
= note: expected type `DIM`
|
||||||
|
found type `Self::DIM`
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
31
src/test/ui/const-generics/issues/issue-85848.rs
Normal file
31
src/test/ui/const-generics/issues/issue-85848.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#![feature(const_generics, const_fn_trait_bound, const_evaluatable_checked)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
trait _Contains<T> {
|
||||||
|
const does_contain: bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Contains<T, const Satisfied: bool> {}
|
||||||
|
|
||||||
|
trait Delegates<T> {}
|
||||||
|
|
||||||
|
impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
|
||||||
|
|
||||||
|
const fn contains<A, B>() -> bool
|
||||||
|
where
|
||||||
|
A: _Contains<B>,
|
||||||
|
{
|
||||||
|
A::does_contain
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
|
||||||
|
|
||||||
|
fn writes_to_path<C>(cap: &C) {
|
||||||
|
writes_to_specific_path(&cap);
|
||||||
|
//~^ ERROR: the trait bound `(): _Contains<&C>` is not satisfied [E0277]
|
||||||
|
//~| ERROR: unconstrained generic constant
|
||||||
|
}
|
||||||
|
|
||||||
|
fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
|
||||||
|
|
||||||
|
fn main() {}
|
44
src/test/ui/const-generics/issues/issue-85848.stderr
Normal file
44
src/test/ui/const-generics/issues/issue-85848.stderr
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
error[E0277]: the trait bound `(): _Contains<&C>` is not satisfied
|
||||||
|
--> $DIR/issue-85848.rs:24:5
|
||||||
|
|
|
||||||
|
LL | writes_to_specific_path(&cap);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `_Contains<&C>` is not implemented for `()`
|
||||||
|
...
|
||||||
|
LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
|
||||||
|
| ------------- required by this bound in `writes_to_specific_path`
|
||||||
|
|
|
||||||
|
note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
|
||||||
|
--> $DIR/issue-85848.rs:21:12
|
||||||
|
|
|
||||||
|
LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
|
||||||
|
note: required because of the requirements on the impl of `Delegates<()>` for `&C`
|
||||||
|
--> $DIR/issue-85848.rs:12:12
|
||||||
|
|
|
||||||
|
LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
|
||||||
|
| ^^^^^^^^^^^^ ^
|
||||||
|
|
||||||
|
error: unconstrained generic constant
|
||||||
|
--> $DIR/issue-85848.rs:24:5
|
||||||
|
|
|
||||||
|
LL | writes_to_specific_path(&cap);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
LL | fn writes_to_specific_path<C: Delegates<()>>(cap: &C) {}
|
||||||
|
| ------------- required by this bound in `writes_to_specific_path`
|
||||||
|
|
|
||||||
|
= help: try adding a `where` bound using this expression: `where [(); { contains::<T, U>() }]:`
|
||||||
|
note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
|
||||||
|
--> $DIR/issue-85848.rs:21:12
|
||||||
|
|
|
||||||
|
LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^
|
||||||
|
note: required because of the requirements on the impl of `Delegates<()>` for `&C`
|
||||||
|
--> $DIR/issue-85848.rs:12:12
|
||||||
|
|
|
||||||
|
LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
|
||||||
|
| ^^^^^^^^^^^^ ^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Add table
Add a link
Reference in a new issue