From 242ac57015554a543fb5b67cd5d2720e3e72ff00 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 2 Jul 2021 08:02:11 +0900 Subject: [PATCH 1/5] Fix const-generics ICE related to binding --- compiler/rustc_ty_utils/src/instance.rs | 9 +++- .../ui/const-generics/issues/issue-83765.rs | 38 ++++++++++++++++ .../const-generics/issues/issue-83765.stderr | 29 ++++++++++++ .../ui/const-generics/issues/issue-85848.rs | 31 +++++++++++++ .../const-generics/issues/issue-85848.stderr | 44 +++++++++++++++++++ 5 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/const-generics/issues/issue-83765.rs create mode 100644 src/test/ui/const-generics/issues/issue-83765.stderr create mode 100644 src/test/ui/const-generics/issues/issue-85848.rs create mode 100644 src/test/ui/const-generics/issues/issue-85848.stderr diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 874289d02938d..98a1c614a43ea 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -115,7 +115,14 @@ fn resolve_associated_item<'tcx>( ); 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)))?; + let vtbl = if trait_item.kind == ty::AssocKind::Const { + let bound_vars = tcx + .mk_bound_variable_kinds(std::iter::once(ty::BoundVariableKind::Region(ty::BrAnon(0)))); + let bind = ty::Binder::bind_with_vars(trait_ref, bound_vars); + tcx.codegen_fulfill_obligation((param_env, bind))? + } else { + 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 // the actual function: diff --git a/src/test/ui/const-generics/issues/issue-83765.rs b/src/test/ui/const-generics/issues/issue-83765.rs new file mode 100644 index 0000000000000..f34badc693e76 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-83765.rs @@ -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(&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() {} diff --git a/src/test/ui/const-generics/issues/issue-83765.stderr b/src/test/ui/const-generics/issues/issue-83765.stderr new file mode 100644 index 0000000000000..ef785bf07ebbf --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-83765.stderr @@ -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`. diff --git a/src/test/ui/const-generics/issues/issue-85848.rs b/src/test/ui/const-generics/issues/issue-85848.rs new file mode 100644 index 0000000000000..478719869b2c4 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-85848.rs @@ -0,0 +1,31 @@ +#![feature(const_generics, const_fn_trait_bound, const_evaluatable_checked)] +#![allow(incomplete_features)] + +trait _Contains { + const does_contain: bool; +} + +trait Contains {} + +trait Delegates {} + +impl Delegates for T where T: Contains {} + +const fn contains() -> bool +where + A: _Contains, +{ + A::does_contain +} + +impl Contains() }> for U where T: _Contains {} + +fn writes_to_path(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>(cap: &C) {} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-85848.stderr b/src/test/ui/const-generics/issues/issue-85848.stderr new file mode 100644 index 0000000000000..5e65136a6bc20 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-85848.stderr @@ -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>(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 Contains() }> for U where T: _Contains {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required because of the requirements on the impl of `Delegates<()>` for `&C` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl Delegates for T where T: Contains {} + | ^^^^^^^^^^^^ ^ + +error: unconstrained generic constant + --> $DIR/issue-85848.rs:24:5 + | +LL | writes_to_specific_path(&cap); + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn writes_to_specific_path>(cap: &C) {} + | ------------- required by this bound in `writes_to_specific_path` + | + = help: try adding a `where` bound using this expression: `where [(); { contains::() }]:` +note: required because of the requirements on the impl of `Contains<(), true>` for `&C` + --> $DIR/issue-85848.rs:21:12 + | +LL | impl Contains() }> for U where T: _Contains {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ +note: required because of the requirements on the impl of `Delegates<()>` for `&C` + --> $DIR/issue-85848.rs:12:12 + | +LL | impl Delegates for T where T: Contains {} + | ^^^^^^^^^^^^ ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From 13e116f1f70cce9759ce7d957e23241895542ec9 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 2 Jul 2021 10:14:13 +0900 Subject: [PATCH 2/5] Use `BoundVarsCollector` for now --- compiler/rustc_middle/src/ty/util.rs | 6 +- compiler/rustc_ty_utils/src/instance.rs | 100 +++++++++++++++++++++--- compiler/rustc_ty_utils/src/lib.rs | 1 + 3 files changed, 97 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 7bf69b9e637e9..24a9cea6d2187 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -7,7 +7,7 @@ use crate::ty::layout::IntegerExt; use crate::ty::query::TyCtxtAt; use crate::ty::subst::{GenericArgKind, Subst, SubstsRef}; 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_ast as ast; use rustc_attr::{self as attr, SignedInt, UnsignedInt}; @@ -905,6 +905,10 @@ impl<'tcx> ty::TyS<'tcx> { } ty } + + pub fn outer_exclusive_binder(&'tcx self) -> DebruijnIndex { + self.outer_exclusive_binder + } } pub enum ExplicitSelf<'tcx> { diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 98a1c614a43ea..ac10ebd2dd7b0 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -2,14 +2,98 @@ use rustc_errors::ErrorReported; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::TyCtxtInferExt; 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_target::spec::abi::Abi; use rustc_trait_selection::traits; use traits::{translate_substs, Reveal}; +use rustc_data_structures::sso::SsoHashSet; +use std::collections::BTreeMap; +use std::ops::ControlFlow; + 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, + // 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 { + 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>( + &mut self, + t: &Binder<'tcx, T>, + ) -> ControlFlow { + 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 { + 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 { + r.super_visit_with(self) + } +} + #[instrument(level = "debug", skip(tcx))] fn resolve_instance<'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 vtbl = if trait_item.kind == ty::AssocKind::Const { - let bound_vars = tcx - .mk_bound_variable_kinds(std::iter::once(ty::BoundVariableKind::Region(ty::BrAnon(0)))); - let bind = ty::Binder::bind_with_vars(trait_ref, bound_vars); - tcx.codegen_fulfill_obligation((param_env, bind))? - } else { - 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 // the actual function: diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index 67a692eceacc4..313571274c3de 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -5,6 +5,7 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(control_flow_enum)] #![feature(half_open_range_patterns)] #![feature(exclusive_range_pattern)] #![feature(nll)] From e28a93365abfa6b506f2017eac2f0971fc839306 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 2 Jul 2021 18:14:28 +0900 Subject: [PATCH 3/5] Correct `visit_region` implementation --- compiler/rustc_ty_utils/src/instance.rs | 27 ++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index ac10ebd2dd7b0..0f507cfb997a5 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -39,7 +39,7 @@ impl<'tcx> BoundVarsCollector<'tcx> { } fn into_vars(self, tcx: TyCtxt<'tcx>) -> &'tcx ty::List { - let max = self.vars.iter().map(|(k, _)| *k).max().unwrap_or_else(|| 0); + 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); @@ -90,6 +90,31 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { } fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { + use std::collections::btree_map::Entry; + match r { + ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind { + ty::BrNamed(_def_id, _name) => { + // FIXME + } + + ty::BrAnon(var) => match self.vars.entry(var) { + Entry::Vacant(entry) => { + entry.insert(ty::BoundVariableKind::Region(br.kind)); + } + Entry::Occupied(entry) => match entry.get() { + ty::BoundVariableKind::Region(_) => {} + _ => bug!("Conflicting bound vars"), + }, + }, + + ty::BrEnv => { + // FIXME + } + }, + + _ => (), + }; + r.super_visit_with(self) } } From 884053a4b422e63a78eddd7b49793c32020d321b Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 2 Jul 2021 18:48:34 +0900 Subject: [PATCH 4/5] Remove `ty::Binder::bind()` Co-authored-by: Noah Lev --- compiler/rustc_middle/src/ty/fold.rs | 82 ------------------- compiler/rustc_middle/src/ty/sty.rs | 8 -- .../src/transform/check_consts/validation.rs | 7 +- .../src/traits/project.rs | 2 +- compiler/rustc_typeck/src/astconv/mod.rs | 2 +- .../rustc_typeck/src/check/compare_method.rs | 11 +-- .../rustc_typeck/src/check/method/confirm.rs | 10 ++- compiler/rustc_typeck/src/check/method/mod.rs | 2 +- compiler/rustc_typeck/src/check/wfcheck.rs | 6 +- compiler/rustc_typeck/src/collect.rs | 18 ++-- 10 files changed, 26 insertions(+), 122 deletions(-) diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index eb6d163312c83..a40210d5a3622 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -754,88 +754,6 @@ impl<'tcx> TyCtxt<'tcx> { } } -pub struct BoundVarsCollector<'tcx> { - binder_index: ty::DebruijnIndex, - vars: BTreeMap, - // 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 { - 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>( - &mut self, - t: &Binder<'tcx, T>, - ) -> ControlFlow { - 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 { - 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 { - 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> { bound_vars: &'tcx ty::List, binder_index: ty::DebruijnIndex, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 2959ea24d2424..73f0811a50429 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -5,7 +5,6 @@ use self::TyKind::*; use crate::infer::canonical::Canonical; -use crate::ty::fold::BoundVarsCollector; use crate::ty::fold::ValidateBoundVars; use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; use crate::ty::InferTy::{self, *}; @@ -970,13 +969,6 @@ where 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) -> Binder<'tcx, T> { if cfg!(debug_assertions) { let mut validator = ValidateBoundVars::new(vars); diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 4fbd27c89d9c8..6216ff6656e28 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -822,12 +822,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { let obligation = Obligation::new( ObligationCause::dummy(), param_env, - Binder::bind( - TraitPredicate { - trait_ref: TraitRef::from_method(tcx, trait_id, substs), - }, - tcx, - ), + Binder::dummy(TraitPredicate { trait_ref }), ); let implsrc = tcx.infer_ctxt().enter(|infcx| { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 388413ae06b55..352829234a41a 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1301,7 +1301,7 @@ fn confirm_pointee_candidate<'cx, '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>( diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 10a7d69d5d3b7..2e42d65cce29b 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -1694,7 +1694,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; 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(), assoc_ident, span, diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index 95a1bfbbb01cf..12d0c14a3d51a 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -222,12 +222,7 @@ fn compare_predicate_entailment<'tcx>( 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, _) = infcx.replace_bound_vars_with_fresh_vars( - impl_m_span, - infer::HigherRankedType, - ty::Binder::bind(impl_m_own_bounds.predicates, tcx), - ); - for predicate in impl_m_own_bounds { + for predicate in impl_m_own_bounds.predicates { let traits::Normalized { value: predicate, obligations } = traits::normalize(&mut selcx, param_env, normalize_cause.clone(), predicate); @@ -258,14 +253,14 @@ fn compare_predicate_entailment<'tcx>( ); let 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); 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 = 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); diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index f546a0d896354..75299bae5ddfd 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -101,6 +101,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { let (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. 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 // a custom error in that case. if illegal_sized_bound.is_none() { - let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig, self.tcx)); - self.add_obligations(method_ty, all_substs, method_predicates); + self.add_obligations(self.tcx.mk_fn_ptr(method_sig), all_substs, method_predicates); } // 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 } } diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index be6bc625d893f..2136d925423b9 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds)); // 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!( "lookup_in_trait_adjusted: matched method method_ty={:?} obligation={:?}", method_ty, obligation diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 7436edccf84bb..dae112621895d 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1087,14 +1087,10 @@ fn check_method_receiver<'fcx, 'tcx>( debug!("check_method_receiver: sig={:?}", sig); 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 self_ty = fcx.tcx.liberate_late_bound_regions(method.def_id, ty::Binder::dummy(self_ty)); let receiver_ty = sig.inputs()[0]; - 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 !receiver_is_valid(fcx, span, receiver_ty, self_ty, true) { diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 91e65cffc58c5..b0e5453b7db92 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1737,11 +1737,12 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { ty::ReErased => tcx.lifetimes.re_static, _ => r, }); + let fn_sig = ty::Binder::dummy(fn_sig); let mut visitor = PlaceholderHirTyCollector::default(); visitor.visit_ty(ty); 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.is_closure() { let ret_ty_str = match ret_ty.kind() { @@ -1767,7 +1768,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { } diag.emit(); - ty::Binder::bind(fn_sig, tcx) + fn_sig } None => >::ty_of_fn( &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 inputs = data.fields().iter().map(|f| tcx.type_of(tcx.hir().local_def_id(f.hir_id))); - ty::Binder::bind( - tcx.mk_fn_sig(inputs, ty, false, hir::Unsafety::Normal, abi::Abi::Rust), - tcx, - ) + ty::Binder::dummy(tcx.mk_fn_sig( + inputs, + ty, + false, + hir::Unsafety::Normal, + abi::Abi::Rust, + )) } 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 { hir::GenericBound::Outlives(lt) => { let bound = >::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)); } _ => bug!(), From 58f6cb4557b2d63d311420bbf6bc63aa119f8306 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 3 Jul 2021 02:13:17 +0900 Subject: [PATCH 5/5] Simplify `visit_region` implementation --- compiler/rustc_ty_utils/src/instance.rs | 17 ++++------------- compiler/rustc_typeck/src/check/wfcheck.rs | 1 - 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 0f507cfb997a5..469ac04e54515 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -9,6 +9,7 @@ use rustc_trait_selection::traits; 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; @@ -69,7 +70,6 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { { 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()) { @@ -90,14 +90,9 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { } fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow { - use std::collections::btree_map::Entry; match r { - ty::ReLateBound(index, br) if *index == self.binder_index => match br.kind { - ty::BrNamed(_def_id, _name) => { - // FIXME - } - - ty::BrAnon(var) => match self.vars.entry(var) { + 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)); } @@ -105,12 +100,8 @@ impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> { ty::BoundVariableKind::Region(_) => {} _ => bug!("Conflicting bound vars"), }, - }, - - ty::BrEnv => { - // FIXME } - }, + } _ => (), }; diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index dae112621895d..0e063c86f2f4e 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -1087,7 +1087,6 @@ fn check_method_receiver<'fcx, 'tcx>( debug!("check_method_receiver: sig={:?}", sig); 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::dummy(self_ty)); let receiver_ty = sig.inputs()[0]; let receiver_ty = fcx.normalize_associated_types_in(span, receiver_ty);