Auto merge of #140375 - lcnr:subrelations-infcx, r=BoxyUwU
eagerly compute `sub_unification_table` again Previously called `sub_relations`. We still only using them for diagnostics right now. This mostly reverts rust-lang/rust#119989. Necessary for type inference guidance due to not-yet defined opaque types, cc https://github.com/rust-lang/trait-system-refactor-initiative/issues/182. We could use them for cycle detection in generalization and it seems desirable to do so in the future. However, this is unsound with the old trait solver as its cache does not track these `sub_unification_table` in any way. We now properly track the `sub_unification_table` when canonicalizing so using them in the new solver is totally sound and the performance impact is far more manageable than I thought back in rust-lang/rust#119989. r? `@compiler-errors`
This commit is contained in:
commit
9c27f27ea3
33 changed files with 586 additions and 571 deletions
|
|
@ -4681,6 +4681,7 @@ dependencies = [
|
|||
name = "rustc_type_ir"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
"derive-where",
|
||||
"ena",
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
|
|||
use rustc_session::Session;
|
||||
use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym};
|
||||
use rustc_trait_selection::error_reporting::TypeErrCtxt;
|
||||
use rustc_trait_selection::error_reporting::infer::sub_relations::SubRelations;
|
||||
use rustc_trait_selection::traits::{
|
||||
self, FulfillmentError, ObligationCause, ObligationCauseCode, ObligationCtxt,
|
||||
};
|
||||
|
|
@ -188,14 +187,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
///
|
||||
/// [`InferCtxtErrorExt::err_ctxt`]: rustc_trait_selection::error_reporting::InferCtxtErrorExt::err_ctxt
|
||||
pub(crate) fn err_ctxt(&'a self) -> TypeErrCtxt<'a, 'tcx> {
|
||||
let mut sub_relations = SubRelations::default();
|
||||
sub_relations.add_constraints(
|
||||
self,
|
||||
self.fulfillment_cx.borrow_mut().pending_obligations().iter().map(|o| o.predicate),
|
||||
);
|
||||
TypeErrCtxt {
|
||||
infcx: &self.infcx,
|
||||
sub_relations: RefCell::new(sub_relations),
|
||||
typeck_results: Some(self.typeck_results.borrow()),
|
||||
fallback_has_occurred: self.fallback_has_occurred.get(),
|
||||
normalize_fn_sig: Box::new(|fn_sig| {
|
||||
|
|
|
|||
|
|
@ -403,15 +403,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// special handling for this "trivial case" is a good idea.
|
||||
|
||||
let infcx = &self.infcx;
|
||||
let (ParamEnvAnd { param_env: _, value: self_ty }, canonical_inference_vars) =
|
||||
let (ParamEnvAnd { param_env: _, value: self_ty }, var_values) =
|
||||
infcx.instantiate_canonical(span, &query_input.canonical);
|
||||
debug!(?self_ty, ?query_input, "probe_op: Mode::Path");
|
||||
MethodAutoderefStepsResult {
|
||||
steps: infcx.tcx.arena.alloc_from_iter([CandidateStep {
|
||||
self_ty: self.make_query_response_ignoring_pending_obligations(
|
||||
canonical_inference_vars,
|
||||
self_ty,
|
||||
),
|
||||
self_ty: self
|
||||
.make_query_response_ignoring_pending_obligations(var_values, self_ty),
|
||||
autoderefs: 0,
|
||||
from_unsafe_deref: false,
|
||||
unsize: false,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sso::SsoHashMap;
|
||||
use rustc_index::Idx;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{
|
||||
|
|
@ -17,7 +18,7 @@ use tracing::debug;
|
|||
|
||||
use crate::infer::InferCtxt;
|
||||
use crate::infer::canonical::{
|
||||
Canonical, CanonicalQueryInput, CanonicalTyVarKind, CanonicalVarKind, OriginalQueryValues,
|
||||
Canonical, CanonicalQueryInput, CanonicalVarKind, OriginalQueryValues,
|
||||
};
|
||||
|
||||
impl<'tcx> InferCtxt<'tcx> {
|
||||
|
|
@ -293,6 +294,13 @@ struct Canonicalizer<'cx, 'tcx> {
|
|||
// Note that indices is only used once `var_values` is big enough to be
|
||||
// heap-allocated.
|
||||
indices: FxHashMap<GenericArg<'tcx>, BoundVar>,
|
||||
/// Maps each `sub_unification_table_root_var` to the index of the first
|
||||
/// variable which used it.
|
||||
///
|
||||
/// This means in case two type variables have the same sub relations root,
|
||||
/// we set the `sub_root` of the second variable to the position of the first.
|
||||
/// Otherwise the `sub_root` of each type variable is just its own position.
|
||||
sub_root_lookup_table: SsoHashMap<ty::TyVid, usize>,
|
||||
canonicalize_mode: &'cx dyn CanonicalizeMode,
|
||||
needs_canonical_flags: TypeFlags,
|
||||
|
||||
|
|
@ -361,10 +369,8 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
|
|||
// FIXME: perf problem described in #55921.
|
||||
ui = ty::UniverseIndex::ROOT;
|
||||
}
|
||||
self.canonicalize_ty_var(
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)),
|
||||
t,
|
||||
)
|
||||
let sub_root = self.get_or_insert_sub_root(vid);
|
||||
self.canonicalize_ty_var(CanonicalVarKind::Ty { ui, sub_root }, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -374,7 +380,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
|
|||
if nt != t {
|
||||
return self.fold_ty(nt);
|
||||
} else {
|
||||
self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Int), t)
|
||||
self.canonicalize_ty_var(CanonicalVarKind::Int, t)
|
||||
}
|
||||
}
|
||||
ty::Infer(ty::FloatVar(vid)) => {
|
||||
|
|
@ -382,7 +388,7 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
|
|||
if nt != t {
|
||||
return self.fold_ty(nt);
|
||||
} else {
|
||||
self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Float), t)
|
||||
self.canonicalize_ty_var(CanonicalVarKind::Float, t)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -562,6 +568,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
|
|||
variables: SmallVec::from_slice(base.variables),
|
||||
query_state,
|
||||
indices: FxHashMap::default(),
|
||||
sub_root_lookup_table: Default::default(),
|
||||
binder_index: ty::INNERMOST,
|
||||
};
|
||||
if canonicalizer.query_state.var_values.spilled() {
|
||||
|
|
@ -660,6 +667,13 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_or_insert_sub_root(&mut self, vid: ty::TyVid) -> ty::BoundVar {
|
||||
let root_vid = self.infcx.unwrap().sub_unification_table_root_var(vid);
|
||||
let idx =
|
||||
*self.sub_root_lookup_table.entry(root_vid).or_insert_with(|| self.variables.len());
|
||||
ty::BoundVar::from(idx)
|
||||
}
|
||||
|
||||
/// Replaces the universe indexes used in `var_values` with their index in
|
||||
/// `query_state.universe_map`. This minimizes the maximum universe used in
|
||||
/// the canonicalized value.
|
||||
|
|
@ -679,11 +693,11 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
|
|||
self.variables
|
||||
.iter()
|
||||
.map(|&kind| match kind {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
|
||||
CanonicalVarKind::Int | CanonicalVarKind::Float => {
|
||||
return kind;
|
||||
}
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u]))
|
||||
CanonicalVarKind::Ty { ui, sub_root } => {
|
||||
CanonicalVarKind::Ty { ui: reverse_universe_map[&ui], sub_root }
|
||||
}
|
||||
CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]),
|
||||
CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
pub use instantiate::CanonicalExt;
|
||||
use rustc_index::IndexVec;
|
||||
pub use rustc_middle::infer::canonical::*;
|
||||
use rustc_middle::ty::{self, GenericArg, List, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::infer::{InferCtxt, RegionVariableOrigin};
|
||||
|
|
@ -67,30 +67,12 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
.chain((1..=canonical.max_universe.as_u32()).map(|_| self.create_next_universe()))
|
||||
.collect();
|
||||
|
||||
let canonical_inference_vars =
|
||||
self.instantiate_canonical_vars(span, canonical.variables, |ui| universes[ui]);
|
||||
let result = canonical.instantiate(self.tcx, &canonical_inference_vars);
|
||||
(result, canonical_inference_vars)
|
||||
}
|
||||
|
||||
/// Given the "infos" about the canonical variables from some
|
||||
/// canonical, creates fresh variables with the same
|
||||
/// characteristics (see `instantiate_canonical_var` for
|
||||
/// details). You can then use `instantiate` to instantiate the
|
||||
/// canonical variable with these inference variables.
|
||||
fn instantiate_canonical_vars(
|
||||
&self,
|
||||
span: Span,
|
||||
variables: &List<CanonicalVarKind<'tcx>>,
|
||||
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
|
||||
) -> CanonicalVarValues<'tcx> {
|
||||
CanonicalVarValues {
|
||||
var_values: self.tcx.mk_args_from_iter(
|
||||
variables
|
||||
.iter()
|
||||
.map(|kind| self.instantiate_canonical_var(span, kind, &universe_map)),
|
||||
),
|
||||
}
|
||||
let var_values =
|
||||
CanonicalVarValues::instantiate(self.tcx, &canonical.variables, |var_values, info| {
|
||||
self.instantiate_canonical_var(span, info, &var_values, |ui| universes[ui])
|
||||
});
|
||||
let result = canonical.instantiate(self.tcx, &var_values);
|
||||
(result, var_values)
|
||||
}
|
||||
|
||||
/// Given the "info" about a canonical variable, creates a fresh
|
||||
|
|
@ -105,22 +87,28 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
&self,
|
||||
span: Span,
|
||||
kind: CanonicalVarKind<'tcx>,
|
||||
previous_var_values: &[GenericArg<'tcx>],
|
||||
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
|
||||
) -> GenericArg<'tcx> {
|
||||
match kind {
|
||||
CanonicalVarKind::Ty(ty_kind) => {
|
||||
let ty = match ty_kind {
|
||||
CanonicalTyVarKind::General(ui) => {
|
||||
self.next_ty_var_in_universe(span, universe_map(ui))
|
||||
CanonicalVarKind::Ty { ui, sub_root } => {
|
||||
let vid = self.next_ty_vid_in_universe(span, universe_map(ui));
|
||||
// If this inference variable is related to an earlier variable
|
||||
// via subtyping, we need to add that info to the inference context.
|
||||
if let Some(prev) = previous_var_values.get(sub_root.as_usize()) {
|
||||
if let &ty::Infer(ty::TyVar(sub_root)) = prev.expect_ty().kind() {
|
||||
self.sub_unify_ty_vids_raw(vid, sub_root);
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
CanonicalTyVarKind::Int => self.next_int_var(),
|
||||
|
||||
CanonicalTyVarKind::Float => self.next_float_var(),
|
||||
};
|
||||
ty.into()
|
||||
}
|
||||
Ty::new_var(self.tcx, vid).into()
|
||||
}
|
||||
|
||||
CanonicalVarKind::Int => self.next_int_var().into(),
|
||||
|
||||
CanonicalVarKind::Float => self.next_float_var().into(),
|
||||
|
||||
CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, bound }) => {
|
||||
let universe_mapped = universe_map(universe);
|
||||
let placeholder_mapped = ty::PlaceholderType { universe: universe_mapped, bound };
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use std::iter;
|
|||
use rustc_index::{Idx, IndexVec};
|
||||
use rustc_middle::arena::ArenaAllocatable;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::infer::canonical::CanonicalVarKind;
|
||||
use rustc_middle::ty::{self, BoundVar, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
|
|
@ -413,26 +414,27 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
let mut opt_values: IndexVec<BoundVar, Option<GenericArg<'tcx>>> =
|
||||
IndexVec::from_elem_n(None, query_response.variables.len());
|
||||
|
||||
// In terms of our example above, we are iterating over pairs like:
|
||||
// [(?A, Vec<?0>), ('static, '?1), (?B, ?0)]
|
||||
for (original_value, result_value) in iter::zip(&original_values.var_values, result_values)
|
||||
{
|
||||
match result_value.kind() {
|
||||
GenericArgKind::Type(result_value) => {
|
||||
// e.g., here `result_value` might be `?0` in the example above...
|
||||
if let ty::Bound(debruijn, b) = *result_value.kind() {
|
||||
// ...in which case we would set `canonical_vars[0]` to `Some(?U)`.
|
||||
|
||||
// We disable the instantiation guess for inference variables
|
||||
// and only use it for placeholders. We need to handle the
|
||||
// `sub_root` of type inference variables which would make this
|
||||
// more involved. They are also a lot rarer than region variables.
|
||||
if let ty::Bound(debruijn, b) = *result_value.kind()
|
||||
&& !matches!(
|
||||
query_response.variables[b.var.as_usize()],
|
||||
CanonicalVarKind::Ty { .. }
|
||||
)
|
||||
{
|
||||
// We only allow a `ty::INNERMOST` index in generic parameters.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
opt_values[b.var] = Some(*original_value);
|
||||
}
|
||||
}
|
||||
GenericArgKind::Lifetime(result_value) => {
|
||||
// e.g., here `result_value` might be `'?1` in the example above...
|
||||
if let ty::ReBound(debruijn, b) = result_value.kind() {
|
||||
// ... in which case we would set `canonical_vars[0]` to `Some('static)`.
|
||||
|
||||
// We only allow a `ty::INNERMOST` index in generic parameters.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
opt_values[b.var] = Some(*original_value);
|
||||
|
|
@ -440,8 +442,6 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
}
|
||||
GenericArgKind::Const(result_value) => {
|
||||
if let ty::ConstKind::Bound(debruijn, b) = result_value.kind() {
|
||||
// ...in which case we would set `canonical_vars[0]` to `Some(const X)`.
|
||||
|
||||
// We only allow a `ty::INNERMOST` index in generic parameters.
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
opt_values[b.var] = Some(*original_value);
|
||||
|
|
@ -453,39 +453,36 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
// Create result arguments: if we found a value for a
|
||||
// given variable in the loop above, use that. Otherwise, use
|
||||
// a fresh inference variable.
|
||||
let result_args = CanonicalVarValues {
|
||||
var_values: self.tcx.mk_args_from_iter(
|
||||
query_response.variables.iter().enumerate().map(|(index, var_kind)| {
|
||||
if var_kind.universe() != ty::UniverseIndex::ROOT {
|
||||
// A variable from inside a binder of the query. While ideally these shouldn't
|
||||
// exist at all, we have to deal with them for now.
|
||||
self.instantiate_canonical_var(cause.span, var_kind, |u| {
|
||||
universe_map[u.as_usize()]
|
||||
})
|
||||
} else if var_kind.is_existential() {
|
||||
match opt_values[BoundVar::new(index)] {
|
||||
Some(k) => k,
|
||||
None => self.instantiate_canonical_var(cause.span, var_kind, |u| {
|
||||
universe_map[u.as_usize()]
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
// For placeholders which were already part of the input, we simply map this
|
||||
// universal bound variable back the placeholder of the input.
|
||||
opt_values[BoundVar::new(index)].expect(
|
||||
"expected placeholder to be unified with itself during response",
|
||||
)
|
||||
}
|
||||
}),
|
||||
),
|
||||
};
|
||||
let tcx = self.tcx;
|
||||
let variables = query_response.variables;
|
||||
let var_values = CanonicalVarValues::instantiate(tcx, variables, |var_values, kind| {
|
||||
if kind.universe() != ty::UniverseIndex::ROOT {
|
||||
// A variable from inside a binder of the query. While ideally these shouldn't
|
||||
// exist at all, we have to deal with them for now.
|
||||
self.instantiate_canonical_var(cause.span, kind, &var_values, |u| {
|
||||
universe_map[u.as_usize()]
|
||||
})
|
||||
} else if kind.is_existential() {
|
||||
match opt_values[BoundVar::new(var_values.len())] {
|
||||
Some(k) => k,
|
||||
None => self.instantiate_canonical_var(cause.span, kind, &var_values, |u| {
|
||||
universe_map[u.as_usize()]
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
// For placeholders which were already part of the input, we simply map this
|
||||
// universal bound variable back the placeholder of the input.
|
||||
opt_values[BoundVar::new(var_values.len())]
|
||||
.expect("expected placeholder to be unified with itself during response")
|
||||
}
|
||||
});
|
||||
|
||||
let mut obligations = PredicateObligations::new();
|
||||
|
||||
// Carry all newly resolved opaque types to the caller's scope
|
||||
for &(a, b) in &query_response.value.opaque_types {
|
||||
let a = instantiate_value(self.tcx, &result_args, a);
|
||||
let b = instantiate_value(self.tcx, &result_args, b);
|
||||
let a = instantiate_value(self.tcx, &var_values, a);
|
||||
let b = instantiate_value(self.tcx, &var_values, b);
|
||||
debug!(?a, ?b, "constrain opaque type");
|
||||
// We use equate here instead of, for example, just registering the
|
||||
// opaque type's hidden value directly, because the hidden type may have been an inference
|
||||
|
|
@ -502,7 +499,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
Ok(InferOk { value: result_args, obligations })
|
||||
Ok(InferOk { value: var_values, obligations })
|
||||
}
|
||||
|
||||
/// Given a "guess" at the values for the canonical variables in
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
|||
self.root_var(var)
|
||||
}
|
||||
|
||||
fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid {
|
||||
self.sub_unification_table_root_var(var)
|
||||
}
|
||||
|
||||
fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
|
||||
self.root_const_var(var)
|
||||
}
|
||||
|
|
@ -179,6 +183,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
|
|||
self.inner.borrow_mut().type_variables().equate(a, b);
|
||||
}
|
||||
|
||||
fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
|
||||
self.sub_unify_ty_vids_raw(a, b);
|
||||
}
|
||||
|
||||
fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid) {
|
||||
self.inner.borrow_mut().int_unification_table().union(a, b);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -764,6 +764,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
let r_b = self.shallow_resolve(predicate.skip_binder().b);
|
||||
match (r_a.kind(), r_b.kind()) {
|
||||
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
|
||||
self.sub_unify_ty_vids_raw(a_vid, b_vid);
|
||||
return Err((a_vid, b_vid));
|
||||
}
|
||||
_ => {}
|
||||
|
|
@ -1128,6 +1129,14 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
self.inner.borrow_mut().type_variables().root_var(var)
|
||||
}
|
||||
|
||||
pub fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
|
||||
self.inner.borrow_mut().type_variables().sub_unify(a, b);
|
||||
}
|
||||
|
||||
pub fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid {
|
||||
self.inner.borrow_mut().type_variables().sub_unification_table_root_var(var)
|
||||
}
|
||||
|
||||
pub fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
|
||||
self.inner.borrow_mut().const_unification_table().find(var).vid
|
||||
}
|
||||
|
|
|
|||
|
|
@ -558,6 +558,10 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
|
|||
let origin = inner.type_variables().var_origin(vid);
|
||||
let new_var_id =
|
||||
inner.type_variables().new_var(self.for_universe, origin);
|
||||
// Record that `vid` and `new_var_id` have to be subtypes
|
||||
// of each other. This is currently only used for diagnostics.
|
||||
// To see why, see the docs in the `type_variables` module.
|
||||
inner.type_variables().sub_unify(vid, new_var_id);
|
||||
// If we're in the new solver and create a new inference
|
||||
// variable inside of an alias we eagerly constrain that
|
||||
// inference variable to prevent unexpected ambiguity errors.
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ pub struct Snapshot<'tcx> {
|
|||
pub(crate) enum UndoLog<'tcx> {
|
||||
DuplicateOpaqueType,
|
||||
OpaqueTypes(OpaqueTypeKey<'tcx>, Option<OpaqueHiddenType<'tcx>>),
|
||||
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
|
||||
TypeVariables(type_variable::UndoLog<'tcx>),
|
||||
ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
|
||||
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
|
||||
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
|
||||
|
|
@ -49,6 +49,8 @@ impl_from! {
|
|||
RegionConstraintCollector(region_constraints::UndoLog<'tcx>),
|
||||
|
||||
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
|
||||
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidSubKey>>),
|
||||
TypeVariables(type_variable::UndoLog<'tcx>),
|
||||
IntUnificationTable(sv::UndoLog<ut::Delegate<ty::IntVid>>),
|
||||
FloatUnificationTable(sv::UndoLog<ut::Delegate<ty::FloatVid>>),
|
||||
|
||||
|
|
|
|||
|
|
@ -13,12 +13,48 @@ use tracing::debug;
|
|||
|
||||
use crate::infer::InferCtxtUndoLogs;
|
||||
|
||||
/// Represents a single undo-able action that affects a type inference variable.
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum UndoLog<'tcx> {
|
||||
EqRelation(sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>),
|
||||
SubRelation(sv::UndoLog<ut::Delegate<TyVidSubKey>>),
|
||||
}
|
||||
|
||||
/// Convert from a specific kind of undo to the more general UndoLog
|
||||
impl<'tcx> From<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for UndoLog<'tcx> {
|
||||
fn from(l: sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>) -> Self {
|
||||
UndoLog::EqRelation(l)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert from a specific kind of undo to the more general UndoLog
|
||||
impl<'tcx> From<sv::UndoLog<ut::Delegate<TyVidSubKey>>> for UndoLog<'tcx> {
|
||||
fn from(l: sv::UndoLog<ut::Delegate<TyVidSubKey>>) -> Self {
|
||||
UndoLog::SubRelation(l)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Rollback<sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>> for TypeVariableStorage<'tcx> {
|
||||
fn reverse(&mut self, undo: sv::UndoLog<ut::Delegate<TyVidEqKey<'tcx>>>) {
|
||||
self.eq_relations.reverse(undo)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Rollback<sv::UndoLog<ut::Delegate<TyVidSubKey>>> for TypeVariableStorage<'tcx> {
|
||||
fn reverse(&mut self, undo: sv::UndoLog<ut::Delegate<TyVidSubKey>>) {
|
||||
self.sub_unification_table.reverse(undo)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Rollback<UndoLog<'tcx>> for TypeVariableStorage<'tcx> {
|
||||
fn reverse(&mut self, undo: UndoLog<'tcx>) {
|
||||
match undo {
|
||||
UndoLog::EqRelation(undo) => self.eq_relations.reverse(undo),
|
||||
UndoLog::SubRelation(undo) => self.sub_unification_table.reverse(undo),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub(crate) struct TypeVariableStorage<'tcx> {
|
||||
/// The origins of each type variable.
|
||||
|
|
@ -27,6 +63,25 @@ pub(crate) struct TypeVariableStorage<'tcx> {
|
|||
/// constraint `?X == ?Y`. This table also stores, for each key,
|
||||
/// the known value.
|
||||
eq_relations: ut::UnificationTableStorage<TyVidEqKey<'tcx>>,
|
||||
/// Only used by `-Znext-solver` and for diagnostics. Tracks whether
|
||||
/// type variables are related via subtyping at all, ignoring which of
|
||||
/// the two is the subtype.
|
||||
///
|
||||
/// When reporting ambiguity errors, we sometimes want to
|
||||
/// treat all inference vars which are subtypes of each
|
||||
/// others as if they are equal. For this case we compute
|
||||
/// the transitive closure of our subtype obligations here.
|
||||
///
|
||||
/// E.g. when encountering ambiguity errors, we want to suggest
|
||||
/// specifying some method argument or to add a type annotation
|
||||
/// to a local variable. Because subtyping cannot change the
|
||||
/// shape of a type, it's fine if the cause of the ambiguity error
|
||||
/// is only related to the suggested variable via subtyping.
|
||||
///
|
||||
/// Even for something like `let x = returns_arg(); x.method();` the
|
||||
/// type of `x` is only a supertype of the argument of `returns_arg`. We
|
||||
/// still want to suggest specifying the type of the argument.
|
||||
sub_unification_table: ut::UnificationTableStorage<TyVidSubKey>,
|
||||
}
|
||||
|
||||
pub(crate) struct TypeVariableTable<'a, 'tcx> {
|
||||
|
|
@ -102,13 +157,24 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
|||
self.storage.values[vid].origin
|
||||
}
|
||||
|
||||
/// Records that `a == b`, depending on `dir`.
|
||||
/// Records that `a == b`.
|
||||
///
|
||||
/// Precondition: neither `a` nor `b` are known.
|
||||
pub(crate) fn equate(&mut self, a: ty::TyVid, b: ty::TyVid) {
|
||||
debug_assert!(self.probe(a).is_unknown());
|
||||
debug_assert!(self.probe(b).is_unknown());
|
||||
self.eq_relations().union(a, b);
|
||||
self.sub_unification_table().union(a, b);
|
||||
}
|
||||
|
||||
/// Records that `a` and `b` are related via subtyping. We don't track
|
||||
/// which of the two is the subtype.
|
||||
///
|
||||
/// Precondition: neither `a` nor `b` are known.
|
||||
pub(crate) fn sub_unify(&mut self, a: ty::TyVid, b: ty::TyVid) {
|
||||
debug_assert!(self.probe(a).is_unknown());
|
||||
debug_assert!(self.probe(b).is_unknown());
|
||||
self.sub_unification_table().union(a, b);
|
||||
}
|
||||
|
||||
/// Instantiates `vid` with the type `ty`.
|
||||
|
|
@ -142,6 +208,10 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
|||
origin: TypeVariableOrigin,
|
||||
) -> ty::TyVid {
|
||||
let eq_key = self.eq_relations().new_key(TypeVariableValue::Unknown { universe });
|
||||
|
||||
let sub_key = self.sub_unification_table().new_key(());
|
||||
debug_assert_eq!(eq_key.vid, sub_key.vid);
|
||||
|
||||
let index = self.storage.values.push(TypeVariableData { origin });
|
||||
debug_assert_eq!(eq_key.vid, index);
|
||||
|
||||
|
|
@ -164,6 +234,18 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
|||
self.eq_relations().find(vid).vid
|
||||
}
|
||||
|
||||
/// Returns the "root" variable of `vid` in the `sub_unification_table`
|
||||
/// equivalence table. All type variables that have been are related via
|
||||
/// equality or subtyping will yield the same root variable (per the
|
||||
/// union-find algorithm), so `sub_unification_table_root_var(a)
|
||||
/// == sub_unification_table_root_var(b)` implies that:
|
||||
/// ```text
|
||||
/// exists X. (a <: X || X <: a) && (b <: X || X <: b)
|
||||
/// ```
|
||||
pub(crate) fn sub_unification_table_root_var(&mut self, vid: ty::TyVid) -> ty::TyVid {
|
||||
self.sub_unification_table().find(vid).vid
|
||||
}
|
||||
|
||||
/// Retrieves the type to which `vid` has been instantiated, if
|
||||
/// any.
|
||||
pub(crate) fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> {
|
||||
|
|
@ -181,6 +263,11 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
|
|||
self.storage.eq_relations.with_log(self.undo_log)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sub_unification_table(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidSubKey> {
|
||||
self.storage.sub_unification_table.with_log(self.undo_log)
|
||||
}
|
||||
|
||||
/// Returns a range of the type variables created during the snapshot.
|
||||
pub(crate) fn vars_since_snapshot(
|
||||
&mut self,
|
||||
|
|
@ -243,6 +330,33 @@ impl<'tcx> ut::UnifyKey for TyVidEqKey<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub(crate) struct TyVidSubKey {
|
||||
vid: ty::TyVid,
|
||||
}
|
||||
|
||||
impl From<ty::TyVid> for TyVidSubKey {
|
||||
#[inline] // make this function eligible for inlining - it is quite hot.
|
||||
fn from(vid: ty::TyVid) -> Self {
|
||||
TyVidSubKey { vid }
|
||||
}
|
||||
}
|
||||
|
||||
impl ut::UnifyKey for TyVidSubKey {
|
||||
type Value = ();
|
||||
#[inline]
|
||||
fn index(&self) -> u32 {
|
||||
self.vid.as_u32()
|
||||
}
|
||||
#[inline]
|
||||
fn from_index(i: u32) -> TyVidSubKey {
|
||||
TyVidSubKey { vid: ty::TyVid::from_u32(i) }
|
||||
}
|
||||
fn tag() -> &'static str {
|
||||
"TyVidSubKey"
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> {
|
||||
type Error = ut::NoError;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ use rustc_data_structures::fx::FxHashMap;
|
|||
use rustc_data_structures::sync::Lock;
|
||||
use rustc_macros::{HashStable, TypeFoldable, TypeVisitable};
|
||||
pub use rustc_type_ir as ir;
|
||||
pub use rustc_type_ir::CanonicalTyVarKind;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::mir::ConstraintCategory;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@ use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack};
|
|||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::solve::{Goal, QueryInput};
|
||||
use rustc_type_ir::{
|
||||
self as ty, Canonical, CanonicalParamEnvCacheEntry, CanonicalTyVarKind, CanonicalVarKind,
|
||||
Flags, InferCtxtLike, Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable,
|
||||
TypeVisitableExt,
|
||||
self as ty, Canonical, CanonicalParamEnvCacheEntry, CanonicalVarKind, Flags, InferCtxtLike,
|
||||
Interner, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
||||
};
|
||||
|
||||
use crate::delegate::SolverDelegate;
|
||||
|
|
@ -68,6 +67,13 @@ pub struct Canonicalizer<'a, D: SolverDelegate<Interner = I>, I: Interner> {
|
|||
variables: &'a mut Vec<I::GenericArg>,
|
||||
var_kinds: Vec<CanonicalVarKind<I>>,
|
||||
variable_lookup_table: HashMap<I::GenericArg, usize>,
|
||||
/// Maps each `sub_unification_table_root_var` to the index of the first
|
||||
/// variable which used it.
|
||||
///
|
||||
/// This means in case two type variables have the same sub relations root,
|
||||
/// we set the `sub_root` of the second variable to the position of the first.
|
||||
/// Otherwise the `sub_root` of each type variable is just its own position.
|
||||
sub_root_lookup_table: HashMap<ty::TyVid, usize>,
|
||||
binder_index: ty::DebruijnIndex,
|
||||
|
||||
/// We only use the debruijn index during lookup. We don't need to
|
||||
|
|
@ -89,6 +95,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||
|
||||
variables,
|
||||
variable_lookup_table: Default::default(),
|
||||
sub_root_lookup_table: Default::default(),
|
||||
var_kinds: Vec::new(),
|
||||
binder_index: ty::INNERMOST,
|
||||
|
||||
|
|
@ -133,6 +140,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||
|
||||
variables: &mut variables,
|
||||
variable_lookup_table: Default::default(),
|
||||
sub_root_lookup_table: Default::default(),
|
||||
var_kinds: Vec::new(),
|
||||
binder_index: ty::INNERMOST,
|
||||
|
||||
|
|
@ -140,6 +148,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||
};
|
||||
let param_env = param_env.fold_with(&mut env_canonicalizer);
|
||||
debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
|
||||
debug_assert!(env_canonicalizer.sub_root_lookup_table.is_empty());
|
||||
CanonicalParamEnvCacheEntry {
|
||||
param_env,
|
||||
variable_lookup_table: env_canonicalizer.variable_lookup_table,
|
||||
|
|
@ -165,6 +174,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||
|
||||
variables,
|
||||
variable_lookup_table: Default::default(),
|
||||
sub_root_lookup_table: Default::default(),
|
||||
var_kinds: Vec::new(),
|
||||
binder_index: ty::INNERMOST,
|
||||
|
||||
|
|
@ -172,6 +182,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||
};
|
||||
let param_env = param_env.fold_with(&mut env_canonicalizer);
|
||||
debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
|
||||
debug_assert!(env_canonicalizer.sub_root_lookup_table.is_empty());
|
||||
(param_env, env_canonicalizer.variable_lookup_table, env_canonicalizer.var_kinds)
|
||||
}
|
||||
}
|
||||
|
|
@ -200,6 +211,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||
|
||||
variables,
|
||||
variable_lookup_table,
|
||||
sub_root_lookup_table: Default::default(),
|
||||
var_kinds,
|
||||
binder_index: ty::INNERMOST,
|
||||
|
||||
|
|
@ -266,6 +278,13 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||
ty::BoundVar::from(idx)
|
||||
}
|
||||
|
||||
fn get_or_insert_sub_root(&mut self, vid: ty::TyVid) -> ty::BoundVar {
|
||||
let root_vid = self.delegate.sub_unification_table_root_var(vid);
|
||||
let idx =
|
||||
*self.sub_root_lookup_table.entry(root_vid).or_insert_with(|| self.variables.len());
|
||||
ty::BoundVar::from(idx)
|
||||
}
|
||||
|
||||
fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVarKinds) {
|
||||
let mut var_kinds = self.var_kinds;
|
||||
// See the rustc-dev-guide section about how we deal with universes
|
||||
|
|
@ -313,18 +332,15 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||
"ty vid should have been resolved fully before canonicalization"
|
||||
);
|
||||
|
||||
match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input { .. } => CanonicalVarKind::Ty(
|
||||
CanonicalTyVarKind::General(ty::UniverseIndex::ROOT),
|
||||
),
|
||||
CanonicalizeMode::Response { .. } => {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(
|
||||
self.delegate.universe_of_ty(vid).unwrap_or_else(|| {
|
||||
panic!("ty var should have been resolved: {t:?}")
|
||||
}),
|
||||
))
|
||||
}
|
||||
}
|
||||
let sub_root = self.get_or_insert_sub_root(vid);
|
||||
let ui = match self.canonicalize_mode {
|
||||
CanonicalizeMode::Input { .. } => ty::UniverseIndex::ROOT,
|
||||
CanonicalizeMode::Response { .. } => self
|
||||
.delegate
|
||||
.universe_of_ty(vid)
|
||||
.unwrap_or_else(|| panic!("ty var should have been resolved: {t:?}")),
|
||||
};
|
||||
CanonicalVarKind::Ty { ui, sub_root }
|
||||
}
|
||||
ty::IntVar(vid) => {
|
||||
debug_assert_eq!(
|
||||
|
|
@ -332,7 +348,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||
t,
|
||||
"ty vid should have been resolved fully before canonicalization"
|
||||
);
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
|
||||
CanonicalVarKind::Int
|
||||
}
|
||||
ty::FloatVar(vid) => {
|
||||
debug_assert_eq!(
|
||||
|
|
@ -340,7 +356,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
|
|||
t,
|
||||
"ty vid should have been resolved fully before canonicalization"
|
||||
);
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Float)
|
||||
CanonicalVarKind::Float
|
||||
}
|
||||
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
|
||||
panic!("fresh vars not expected in canonicalization")
|
||||
|
|
|
|||
|
|
@ -57,12 +57,14 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
|
|||
where
|
||||
V: TypeFoldable<Self::Interner>;
|
||||
|
||||
fn instantiate_canonical_var_with_infer(
|
||||
fn instantiate_canonical_var(
|
||||
&self,
|
||||
kind: ty::CanonicalVarKind<Self::Interner>,
|
||||
span: <Self::Interner as Interner>::Span,
|
||||
var_values: &[<Self::Interner as Interner>::GenericArg],
|
||||
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
|
||||
) -> <Self::Interner as Interner>::GenericArg;
|
||||
|
||||
fn add_item_bounds_for_hidden_type(
|
||||
&self,
|
||||
def_id: <Self::Interner as Interner>::DefId,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ use rustc_type_ir::data_structures::HashSet;
|
|||
use rustc_type_ir::inherent::*;
|
||||
use rustc_type_ir::relate::solver_relating::RelateExt;
|
||||
use rustc_type_ir::{
|
||||
self as ty, Canonical, CanonicalVarValues, InferCtxtLike, Interner, TypeFoldable,
|
||||
self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner,
|
||||
TypeFoldable,
|
||||
};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
|
|
@ -336,7 +337,16 @@ where
|
|||
{
|
||||
match result_value.kind() {
|
||||
ty::GenericArgKind::Type(t) => {
|
||||
if let ty::Bound(debruijn, b) = t.kind() {
|
||||
// We disable the instantiation guess for inference variables
|
||||
// and only use it for placeholders. We need to handle the
|
||||
// `sub_root` of type inference variables which would make this
|
||||
// more involved. They are also a lot rarer than region variables.
|
||||
if let ty::Bound(debruijn, b) = t.kind()
|
||||
&& !matches!(
|
||||
response.variables.get(b.var().as_usize()).unwrap(),
|
||||
CanonicalVarKind::Ty { .. }
|
||||
)
|
||||
{
|
||||
assert_eq!(debruijn, ty::INNERMOST);
|
||||
opt_values[b.var()] = Some(*original_value);
|
||||
}
|
||||
|
|
@ -355,39 +365,33 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
let var_values = delegate.cx().mk_args_from_iter(
|
||||
response.variables.iter().enumerate().map(|(index, var_kind)| {
|
||||
if var_kind.universe() != ty::UniverseIndex::ROOT {
|
||||
// A variable from inside a binder of the query. While ideally these shouldn't
|
||||
// exist at all (see the FIXME at the start of this method), we have to deal with
|
||||
// them for now.
|
||||
delegate.instantiate_canonical_var_with_infer(var_kind, span, |idx| {
|
||||
prev_universe + idx.index()
|
||||
})
|
||||
} else if var_kind.is_existential() {
|
||||
// As an optimization we sometimes avoid creating a new inference variable here.
|
||||
//
|
||||
// All new inference variables we create start out in the current universe of the caller.
|
||||
// This is conceptually wrong as these inference variables would be able to name
|
||||
// more placeholders then they should be able to. However the inference variables have
|
||||
// to "come from somewhere", so by equating them with the original values of the caller
|
||||
// later on, we pull them down into their correct universe again.
|
||||
if let Some(v) = opt_values[ty::BoundVar::from_usize(index)] {
|
||||
v
|
||||
} else {
|
||||
delegate
|
||||
.instantiate_canonical_var_with_infer(var_kind, span, |_| prev_universe)
|
||||
}
|
||||
CanonicalVarValues::instantiate(delegate.cx(), response.variables, |var_values, kind| {
|
||||
if kind.universe() != ty::UniverseIndex::ROOT {
|
||||
// A variable from inside a binder of the query. While ideally these shouldn't
|
||||
// exist at all (see the FIXME at the start of this method), we have to deal with
|
||||
// them for now.
|
||||
delegate.instantiate_canonical_var(kind, span, &var_values, |idx| {
|
||||
prev_universe + idx.index()
|
||||
})
|
||||
} else if kind.is_existential() {
|
||||
// As an optimization we sometimes avoid creating a new inference variable here.
|
||||
//
|
||||
// All new inference variables we create start out in the current universe of the caller.
|
||||
// This is conceptually wrong as these inference variables would be able to name
|
||||
// more placeholders then they should be able to. However the inference variables have
|
||||
// to "come from somewhere", so by equating them with the original values of the caller
|
||||
// later on, we pull them down into their correct universe again.
|
||||
if let Some(v) = opt_values[ty::BoundVar::from_usize(var_values.len())] {
|
||||
v
|
||||
} else {
|
||||
// For placeholders which were already part of the input, we simply map this
|
||||
// universal bound variable back the placeholder of the input.
|
||||
original_values[var_kind.expect_placeholder_index()]
|
||||
delegate.instantiate_canonical_var(kind, span, &var_values, |_| prev_universe)
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
CanonicalVarValues { var_values }
|
||||
} else {
|
||||
// For placeholders which were already part of the input, we simply map this
|
||||
// universal bound variable back the placeholder of the input.
|
||||
original_values[kind.expect_placeholder_index()]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Unify the `original_values` with the `var_values` returned by the canonical query..
|
||||
|
|
|
|||
|
|
@ -900,6 +900,10 @@ where
|
|||
&& goal.param_env.visit_with(&mut visitor).is_continue()
|
||||
}
|
||||
|
||||
pub(super) fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid) {
|
||||
self.delegate.sub_unify_ty_vids_raw(a, b)
|
||||
}
|
||||
|
||||
#[instrument(level = "trace", skip(self, param_env), ret)]
|
||||
pub(super) fn eq<T: Relate<I>>(
|
||||
&mut self,
|
||||
|
|
|
|||
|
|
@ -119,11 +119,15 @@ where
|
|||
|
||||
#[instrument(level = "trace", skip(self))]
|
||||
fn compute_subtype_goal(&mut self, goal: Goal<I, ty::SubtypePredicate<I>>) -> QueryResult<I> {
|
||||
if goal.predicate.a.is_ty_var() && goal.predicate.b.is_ty_var() {
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
||||
} else {
|
||||
self.sub(goal.param_env, goal.predicate.a, goal.predicate.b)?;
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
match (goal.predicate.a.kind(), goal.predicate.b.kind()) {
|
||||
(ty::Infer(ty::TyVar(a_vid)), ty::Infer(ty::TyVar(b_vid))) => {
|
||||
self.sub_unify_ty_vids_raw(a_vid, b_vid);
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)
|
||||
}
|
||||
_ => {
|
||||
self.sub(goal.param_env, goal.predicate.a, goal.predicate.b)?;
|
||||
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -414,6 +418,11 @@ pub struct GoalEvaluation<I: Interner> {
|
|||
pub has_changed: HasChanged,
|
||||
/// If the [`Certainty`] was `Maybe`, then keep track of whether the goal has changed
|
||||
/// before rerunning it.
|
||||
///
|
||||
/// We knowingly ignore the `sub_root` of our inference variables here. This means we
|
||||
/// may not reevaluate a goal even though a change to the `sub_root` could cause a goal
|
||||
/// to make progress. Tracking them adds additional complexity for an incredibly minor
|
||||
/// type inference improvement. We could look into properly handling this in the future.
|
||||
pub stalled_on: Option<GoalStalledOn<I>>,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,6 @@ mod suggest;
|
|||
pub mod need_type_info;
|
||||
pub mod nice_region_error;
|
||||
pub mod region;
|
||||
pub mod sub_relations;
|
||||
|
||||
/// Makes a valid string literal from a string by escaping special characters (" and \),
|
||||
/// unless they are already escaped.
|
||||
|
|
|
|||
|
|
@ -894,7 +894,8 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
|
|||
use ty::{Infer, TyVar};
|
||||
match (inner_ty.kind(), target_ty.kind()) {
|
||||
(&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
|
||||
self.tecx.sub_relations.borrow_mut().unified(self.tecx, a_vid, b_vid)
|
||||
self.tecx.sub_unification_table_root_var(a_vid)
|
||||
== self.tecx.sub_unification_table_root_var(b_vid)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,81 +0,0 @@
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::undo_log::NoUndo;
|
||||
use rustc_data_structures::unify as ut;
|
||||
use rustc_middle::ty;
|
||||
|
||||
use crate::infer::InferCtxt;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
struct SubId(u32);
|
||||
impl ut::UnifyKey for SubId {
|
||||
type Value = ();
|
||||
#[inline]
|
||||
fn index(&self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
#[inline]
|
||||
fn from_index(i: u32) -> SubId {
|
||||
SubId(i)
|
||||
}
|
||||
fn tag() -> &'static str {
|
||||
"SubId"
|
||||
}
|
||||
}
|
||||
|
||||
/// When reporting ambiguity errors, we sometimes want to
|
||||
/// treat all inference vars which are subtypes of each
|
||||
/// others as if they are equal. For this case we compute
|
||||
/// the transitive closure of our subtype obligations here.
|
||||
///
|
||||
/// E.g. when encountering ambiguity errors, we want to suggest
|
||||
/// specifying some method argument or to add a type annotation
|
||||
/// to a local variable. Because subtyping cannot change the
|
||||
/// shape of a type, it's fine if the cause of the ambiguity error
|
||||
/// is only related to the suggested variable via subtyping.
|
||||
///
|
||||
/// Even for something like `let x = returns_arg(); x.method();` the
|
||||
/// type of `x` is only a supertype of the argument of `returns_arg`. We
|
||||
/// still want to suggest specifying the type of the argument.
|
||||
#[derive(Default)]
|
||||
pub struct SubRelations {
|
||||
map: FxHashMap<ty::TyVid, SubId>,
|
||||
table: ut::UnificationTableStorage<SubId>,
|
||||
}
|
||||
|
||||
impl SubRelations {
|
||||
fn get_id<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, vid: ty::TyVid) -> SubId {
|
||||
let root_vid = infcx.root_var(vid);
|
||||
*self.map.entry(root_vid).or_insert_with(|| self.table.with_log(&mut NoUndo).new_key(()))
|
||||
}
|
||||
|
||||
pub fn add_constraints<'tcx>(
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
obls: impl IntoIterator<Item = ty::Predicate<'tcx>>,
|
||||
) {
|
||||
for p in obls {
|
||||
let (a, b) = match p.kind().skip_binder() {
|
||||
ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: _, a, b }) => {
|
||||
(a, b)
|
||||
}
|
||||
ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => (a, b),
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
match (a.kind(), b.kind()) {
|
||||
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
|
||||
let a = self.get_id(infcx, a_vid);
|
||||
let b = self.get_id(infcx, b_vid);
|
||||
self.table.with_log(&mut NoUndo).unify_var_var(a, b).unwrap();
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unified<'tcx>(&mut self, infcx: &InferCtxt<'tcx>, a: ty::TyVid, b: ty::TyVid) -> bool {
|
||||
let a = self.get_id(infcx, a);
|
||||
let b = self.get_id(infcx, b);
|
||||
self.table.with_log(&mut NoUndo).unioned(a, b)
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,6 @@ use rustc_macros::extension;
|
|||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
||||
use crate::error_reporting::infer::sub_relations;
|
||||
|
||||
pub mod infer;
|
||||
pub mod traits;
|
||||
|
||||
|
|
@ -21,7 +19,6 @@ pub mod traits;
|
|||
/// methods which should not be used during the happy path.
|
||||
pub struct TypeErrCtxt<'a, 'tcx> {
|
||||
pub infcx: &'a InferCtxt<'tcx>,
|
||||
pub sub_relations: std::cell::RefCell<sub_relations::SubRelations>,
|
||||
|
||||
pub typeck_results: Option<std::cell::Ref<'a, ty::TypeckResults<'tcx>>>,
|
||||
pub fallback_has_occurred: bool,
|
||||
|
|
@ -38,7 +35,6 @@ impl<'tcx> InferCtxt<'tcx> {
|
|||
fn err_ctxt(&self) -> TypeErrCtxt<'_, 'tcx> {
|
||||
TypeErrCtxt {
|
||||
infcx: self,
|
||||
sub_relations: Default::default(),
|
||||
typeck_results: None,
|
||||
fallback_has_occurred: false,
|
||||
normalize_fn_sig: Box::new(|fn_sig| fn_sig),
|
||||
|
|
|
|||
|
|
@ -139,10 +139,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
&self,
|
||||
mut errors: Vec<FulfillmentError<'tcx>>,
|
||||
) -> ErrorGuaranteed {
|
||||
self.sub_relations
|
||||
.borrow_mut()
|
||||
.add_constraints(self, errors.iter().map(|e| e.obligation.predicate));
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ErrorDescriptor<'tcx> {
|
||||
goal: Goal<'tcx, ty::Predicate<'tcx>>,
|
||||
|
|
|
|||
|
|
@ -184,10 +184,9 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
|
|||
R: Debug + TypeFoldable<TyCtxt<'tcx>>,
|
||||
Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
|
||||
{
|
||||
let (infcx, key, canonical_inference_vars) =
|
||||
self.build_with_canonical(DUMMY_SP, canonical_key);
|
||||
let (infcx, key, var_values) = self.build_with_canonical(DUMMY_SP, canonical_key);
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let value = operation(&ocx, key)?;
|
||||
ocx.make_canonicalized_query_response(canonical_inference_vars, value)
|
||||
ocx.make_canonicalized_query_response(var_values, value)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,13 +126,12 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
|||
}
|
||||
ty::PredicateKind::Subtype(ty::SubtypePredicate { a, b, .. })
|
||||
| ty::PredicateKind::Coerce(ty::CoercePredicate { a, b }) => {
|
||||
if self.shallow_resolve(a).is_ty_var() && self.shallow_resolve(b).is_ty_var() {
|
||||
// FIXME: We also need to register a subtype relation between these vars
|
||||
// when those are added, and if they aren't in the same sub root then
|
||||
// we should mark this goal as `has_changed`.
|
||||
Some(Certainty::AMBIGUOUS)
|
||||
} else {
|
||||
None
|
||||
match (self.shallow_resolve(a).kind(), self.shallow_resolve(b).kind()) {
|
||||
(&ty::Infer(ty::TyVar(a_vid)), &ty::Infer(ty::TyVar(b_vid))) => {
|
||||
self.sub_unify_ty_vids_raw(a_vid, b_vid);
|
||||
Some(Certainty::AMBIGUOUS)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) => {
|
||||
|
|
@ -238,13 +237,14 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
|
|||
canonical.instantiate(self.tcx, &values)
|
||||
}
|
||||
|
||||
fn instantiate_canonical_var_with_infer(
|
||||
fn instantiate_canonical_var(
|
||||
&self,
|
||||
kind: CanonicalVarKind<'tcx>,
|
||||
span: Span,
|
||||
var_values: &[ty::GenericArg<'tcx>],
|
||||
universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
|
||||
) -> ty::GenericArg<'tcx> {
|
||||
self.0.instantiate_canonical_var(span, kind, universe_map)
|
||||
self.0.instantiate_canonical_var(span, kind, var_values, universe_map)
|
||||
}
|
||||
|
||||
fn add_item_bounds_for_hidden_type(
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ fn evaluate_obligation<'tcx>(
|
|||
) -> Result<EvaluationResult, OverflowError> {
|
||||
assert!(!tcx.next_trait_solver_globally());
|
||||
debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal);
|
||||
let (ref infcx, goal, _canonical_inference_vars) =
|
||||
let (ref infcx, goal, _var_values) =
|
||||
tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &canonical_goal);
|
||||
debug!("evaluate_obligation: goal={:#?}", goal);
|
||||
let ParamEnvAnd { param_env, value: predicate } = goal;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ edition = "2024"
|
|||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
arrayvec = { version = "0.7", default-features = false }
|
||||
bitflags = "2.4.1"
|
||||
derive-where = "1.2.7"
|
||||
ena = "0.14.3"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::ops::Index;
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
use derive_where::derive_where;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
|
||||
|
|
@ -91,8 +91,18 @@ impl<I: Interner, V: fmt::Display> fmt::Display for Canonical<I, V> {
|
|||
derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
|
||||
)]
|
||||
pub enum CanonicalVarKind<I: Interner> {
|
||||
/// Some kind of type inference variable.
|
||||
Ty(CanonicalTyVarKind),
|
||||
/// General type variable `?T` that can be unified with arbitrary types.
|
||||
///
|
||||
/// We also store the index of the first type variable which is sub-unified
|
||||
/// with this one. If there is no inference variable related to this one,
|
||||
/// its `sub_root` just points to itself.
|
||||
Ty { ui: UniverseIndex, sub_root: ty::BoundVar },
|
||||
|
||||
/// Integral type variable `?I` (that can only be unified with integral types).
|
||||
Int,
|
||||
|
||||
/// Floating-point type variable `?F` (that can only be unified with float types).
|
||||
Float,
|
||||
|
||||
/// A "placeholder" that represents "any type".
|
||||
PlaceholderTy(I::PlaceholderTy),
|
||||
|
|
@ -117,15 +127,13 @@ impl<I: Interner> Eq for CanonicalVarKind<I> {}
|
|||
impl<I: Interner> CanonicalVarKind<I> {
|
||||
pub fn universe(self) -> UniverseIndex {
|
||||
match self {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui,
|
||||
CanonicalVarKind::Ty { ui, sub_root: _ } => ui,
|
||||
CanonicalVarKind::Region(ui) => ui,
|
||||
CanonicalVarKind::Const(ui) => ui,
|
||||
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe(),
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe(),
|
||||
CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.universe(),
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => {
|
||||
UniverseIndex::ROOT
|
||||
}
|
||||
CanonicalVarKind::Float | CanonicalVarKind::Int => UniverseIndex::ROOT,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -135,9 +143,7 @@ impl<I: Interner> CanonicalVarKind<I> {
|
|||
/// the updated universe is not the root.
|
||||
pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarKind<I> {
|
||||
match self {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
|
||||
}
|
||||
CanonicalVarKind::Ty { ui: _, sub_root } => CanonicalVarKind::Ty { ui, sub_root },
|
||||
CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
|
||||
CanonicalVarKind::Const(_) => CanonicalVarKind::Const(ui),
|
||||
|
||||
|
|
@ -150,7 +156,7 @@ impl<I: Interner> CanonicalVarKind<I> {
|
|||
CanonicalVarKind::PlaceholderConst(placeholder) => {
|
||||
CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui))
|
||||
}
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
|
||||
CanonicalVarKind::Int | CanonicalVarKind::Float => {
|
||||
assert_eq!(ui, UniverseIndex::ROOT);
|
||||
self
|
||||
}
|
||||
|
|
@ -159,19 +165,23 @@ impl<I: Interner> CanonicalVarKind<I> {
|
|||
|
||||
pub fn is_existential(self) -> bool {
|
||||
match self {
|
||||
CanonicalVarKind::Ty(_) => true,
|
||||
CanonicalVarKind::PlaceholderTy(_) => false,
|
||||
CanonicalVarKind::Region(_) => true,
|
||||
CanonicalVarKind::PlaceholderRegion(..) => false,
|
||||
CanonicalVarKind::Const(_) => true,
|
||||
CanonicalVarKind::PlaceholderConst(_) => false,
|
||||
CanonicalVarKind::Ty { .. }
|
||||
| CanonicalVarKind::Int
|
||||
| CanonicalVarKind::Float
|
||||
| CanonicalVarKind::Region(_)
|
||||
| CanonicalVarKind::Const(_) => true,
|
||||
CanonicalVarKind::PlaceholderTy(_)
|
||||
| CanonicalVarKind::PlaceholderRegion(..)
|
||||
| CanonicalVarKind::PlaceholderConst(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_region(self) -> bool {
|
||||
match self {
|
||||
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
|
||||
CanonicalVarKind::Ty(_)
|
||||
CanonicalVarKind::Ty { .. }
|
||||
| CanonicalVarKind::Int
|
||||
| CanonicalVarKind::Float
|
||||
| CanonicalVarKind::PlaceholderTy(_)
|
||||
| CanonicalVarKind::Const(_)
|
||||
| CanonicalVarKind::PlaceholderConst(_) => false,
|
||||
|
|
@ -180,7 +190,11 @@ impl<I: Interner> CanonicalVarKind<I> {
|
|||
|
||||
pub fn expect_placeholder_index(self) -> usize {
|
||||
match self {
|
||||
CanonicalVarKind::Ty(_) | CanonicalVarKind::Region(_) | CanonicalVarKind::Const(_) => {
|
||||
CanonicalVarKind::Ty { .. }
|
||||
| CanonicalVarKind::Int
|
||||
| CanonicalVarKind::Float
|
||||
| CanonicalVarKind::Region(_)
|
||||
| CanonicalVarKind::Const(_) => {
|
||||
panic!("expected placeholder: {self:?}")
|
||||
}
|
||||
|
||||
|
|
@ -191,27 +205,6 @@ impl<I: Interner> CanonicalVarKind<I> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Rust actually has more than one category of type variables;
|
||||
/// notably, the type variables we create for literals (e.g., 22 or
|
||||
/// 22.) can only be instantiated with integral/float types (e.g.,
|
||||
/// usize or f32). In order to faithfully reproduce a type, we need to
|
||||
/// know what set of types a given type variable can be unified with.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(
|
||||
feature = "nightly",
|
||||
derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
|
||||
)]
|
||||
pub enum CanonicalTyVarKind {
|
||||
/// General type variable `?T` that can be unified with arbitrary types.
|
||||
General(UniverseIndex),
|
||||
|
||||
/// Integral type variable `?I` (that can only be unified with integral types).
|
||||
Int,
|
||||
|
||||
/// Floating-point type variable `?F` (that can only be unified with float types).
|
||||
Float,
|
||||
}
|
||||
|
||||
/// A set of values corresponding to the canonical variables from some
|
||||
/// `Canonical`. You can give these values to
|
||||
/// `canonical_value.instantiate` to instantiate them into the canonical
|
||||
|
|
@ -287,7 +280,10 @@ impl<I: Interner> CanonicalVarValues<I> {
|
|||
var_values: cx.mk_args_from_iter(infos.iter().enumerate().map(
|
||||
|(i, kind)| -> I::GenericArg {
|
||||
match kind {
|
||||
CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => {
|
||||
CanonicalVarKind::Ty { .. }
|
||||
| CanonicalVarKind::Int
|
||||
| CanonicalVarKind::Float
|
||||
| CanonicalVarKind::PlaceholderTy(_) => {
|
||||
Ty::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
|
||||
.into()
|
||||
}
|
||||
|
|
@ -311,6 +307,37 @@ impl<I: Interner> CanonicalVarValues<I> {
|
|||
CanonicalVarValues { var_values: Default::default() }
|
||||
}
|
||||
|
||||
pub fn instantiate(
|
||||
cx: I,
|
||||
variables: I::CanonicalVarKinds,
|
||||
mut f: impl FnMut(&[I::GenericArg], CanonicalVarKind<I>) -> I::GenericArg,
|
||||
) -> CanonicalVarValues<I> {
|
||||
// Instantiating `CanonicalVarValues` is really hot, but limited to less than
|
||||
// 4 most of the time. Avoid creating a `Vec` here.
|
||||
if variables.len() <= 4 {
|
||||
let mut var_values = ArrayVec::<_, 4>::new();
|
||||
for info in variables.iter() {
|
||||
var_values.push(f(&var_values, info));
|
||||
}
|
||||
CanonicalVarValues { var_values: cx.mk_args(&var_values) }
|
||||
} else {
|
||||
CanonicalVarValues::instantiate_cold(cx, variables, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[cold]
|
||||
fn instantiate_cold(
|
||||
cx: I,
|
||||
variables: I::CanonicalVarKinds,
|
||||
mut f: impl FnMut(&[I::GenericArg], CanonicalVarKind<I>) -> I::GenericArg,
|
||||
) -> CanonicalVarValues<I> {
|
||||
let mut var_values = Vec::with_capacity(variables.len());
|
||||
for info in variables.iter() {
|
||||
var_values.push(f(&var_values, info));
|
||||
}
|
||||
CanonicalVarValues { var_values: cx.mk_args(&var_values) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.var_values.len()
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ pub trait InferCtxtLike: Sized {
|
|||
fn universe_of_ct(&self, ct: ty::ConstVid) -> Option<ty::UniverseIndex>;
|
||||
|
||||
fn root_ty_var(&self, var: ty::TyVid) -> ty::TyVid;
|
||||
fn sub_unification_table_root_var(&self, var: ty::TyVid) -> ty::TyVid;
|
||||
fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid;
|
||||
|
||||
fn opportunistic_resolve_ty_var(&self, vid: ty::TyVid) -> <Self::Interner as Interner>::Ty;
|
||||
|
|
@ -197,6 +198,7 @@ pub trait InferCtxtLike: Sized {
|
|||
) -> U;
|
||||
|
||||
fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
|
||||
fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid);
|
||||
fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid);
|
||||
fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid);
|
||||
fn equate_const_vids_raw(&self, a: ty::ConstVid, b: ty::ConstVid);
|
||||
|
|
|
|||
|
|
@ -1,30 +1,30 @@
|
|||
// MIR for `address_of_reborrow` after SimplifyCfg-initial
|
||||
|
||||
| User Type Annotations
|
||||
| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:8:10: 8:18, inferred_ty: *const [i32; 10]
|
||||
| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:8:10: 8:18, inferred_ty: *const [i32; 10]
|
||||
| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:10:10: 10:25, inferred_ty: *const dyn std::marker::Send
|
||||
| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
|
||||
| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
|
||||
| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
|
||||
| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
|
||||
| 4: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
|
||||
| 5: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
|
||||
| 6: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
|
||||
| 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
|
||||
| 8: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
|
||||
| 9: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
|
||||
| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:19:10: 19:18, inferred_ty: *const [i32; 10]
|
||||
| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:19:10: 19:18, inferred_ty: *const [i32; 10]
|
||||
| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:21:10: 21:25, inferred_ty: *const dyn std::marker::Send
|
||||
| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
|
||||
| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
|
||||
| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
|
||||
| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
|
||||
| 14: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
|
||||
| 15: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
|
||||
| 16: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
|
||||
| 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
|
||||
| 18: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
|
||||
| 19: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
|
||||
| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:29:10: 29:16, inferred_ty: *mut [i32; 10]
|
||||
| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:29:10: 29:16, inferred_ty: *mut [i32; 10]
|
||||
| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:31:10: 31:23, inferred_ty: *mut dyn std::marker::Send
|
||||
| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
|
||||
| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty(General(U0))] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
|
||||
| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
|
||||
| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
|
||||
| 24: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
|
||||
| 25: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
|
||||
| 26: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<svg width="2322px" height="4322px" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="2238px" height="3890px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { background: #000000 }
|
||||
|
|
@ -129,375 +129,327 @@
|
|||
</tspan>
|
||||
<tspan x="10px" y="982px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: the following trait bounds were not satisfied:</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1000px"><tspan> `<Flatten<Map<std::vec::IntoIter<HashSet<u8>>, {closure@$DIR/multiline-removal-suggestion.rs:16:10: 16:13}>> as IntoIterator>::IntoIter = _`</tspan>
|
||||
<tspan x="10px" y="1000px"><tspan> `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:14:8: 14:23}>>: Iterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1018px"><tspan> which is required by `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:14:8: 14:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="1018px"><tspan> which is required by `&mut Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:14:8: 14:23}>>: Iterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1036px"><tspan> `<Flatten<Map<std::vec::IntoIter<HashSet<u8>>, {closure@$DIR/multiline-removal-suggestion.rs:16:10: 16:13}>> as IntoIterator>::Item = _`</tspan>
|
||||
<tspan x="10px" y="1036px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="1054px"><tspan> which is required by `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:14:8: 14:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="1054px"><tspan class="fg-ansi256-009 bold">error[E0277]</tspan><tspan class="bold">: `(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1072px"><tspan> `Flatten<Map<std::vec::IntoIter<HashSet<u8>>, {closure@$DIR/multiline-removal-suggestion.rs:16:10: 16:13}>>: IntoIterator`</tspan>
|
||||
<tspan x="10px" y="1072px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:32:6</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1090px"><tspan> which is required by `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:14:8: 14:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="1090px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1108px"><tspan> `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:14:8: 14:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="1108px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1126px"><tspan> which is required by `&mut Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:14:8: 14:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="1126px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1144px">
|
||||
<tspan x="10px" y="1144px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1162px"><tspan class="fg-ansi256-009 bold">error[E0277]</tspan><tspan class="bold">: `(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
<tspan x="10px" y="1162px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1180px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:32:6</tspan>
|
||||
<tspan x="10px" y="1180px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: required for `(bool, HashSet<u8>)` to implement `IntoIterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1198px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="1198px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required by a bound in `flatten`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1216px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .flatten()</tspan>
|
||||
<tspan x="10px" y="1216px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1234px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
<tspan x="10px" y="1234px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: consider removing this method call, as the receiver has type `std::vec::IntoIter<HashSet<u8>>` and `std::vec::IntoIter<HashSet<u8>>: Iterator` trivially holds</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1252px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1270px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)`</tspan>
|
||||
<tspan x="10px" y="1270px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- </tspan><tspan> ts.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1288px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: required for `(bool, HashSet<u8>)` to implement `IntoIterator`</tspan>
|
||||
<tspan x="10px" y="1288px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- .map(|t| (is_true, t))</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1306px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required by a bound in `flatten`</tspan>
|
||||
<tspan x="10px" y="1306px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-010">+ </tspan><tspan> ts.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1324px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL</tspan>
|
||||
<tspan x="10px" y="1324px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1342px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: consider removing this method call, as the receiver has type `std::vec::IntoIter<HashSet<u8>>` and `std::vec::IntoIter<HashSet<u8>>: Iterator` trivially holds</tspan>
|
||||
<tspan x="10px" y="1342px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="1360px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="1360px"><tspan class="fg-ansi256-009 bold">error[E0277]</tspan><tspan class="bold">: `(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1378px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- </tspan><tspan> ts.into_iter()</tspan>
|
||||
<tspan x="10px" y="1378px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:28:2</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1396px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- .map(|t| (is_true, t))</tspan>
|
||||
<tspan x="10px" y="1396px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1414px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-010">+ </tspan><tspan> ts.into_iter()</tspan>
|
||||
<tspan x="10px" y="1414px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">/</tspan><tspan> hm.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1432px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="1432px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> .map(|(is_true, ts)| {</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1450px">
|
||||
<tspan x="10px" y="1450px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> ts.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1468px"><tspan class="fg-ansi256-009 bold">error[E0277]</tspan><tspan class="bold">: `(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
<tspan x="10px" y="1468px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> .map(|t| (is_true, t))</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1486px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:28:2</tspan>
|
||||
<tspan x="10px" y="1486px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> .flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1504px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="1504px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> })</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1522px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">/</tspan><tspan> hm.into_iter()</tspan>
|
||||
<tspan x="10px" y="1522px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|__________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1540px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> .map(|(is_true, ts)| {</tspan>
|
||||
<tspan x="10px" y="1540px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1558px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> ts.into_iter()</tspan>
|
||||
<tspan x="10px" y="1558px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1576px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> .map(|t| (is_true, t))</tspan>
|
||||
<tspan x="10px" y="1576px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: required for `(bool, HashSet<u8>)` to implement `IntoIterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1594px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> .flatten()</tspan>
|
||||
<tspan x="10px" y="1594px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required by a bound in `Flatten`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1612px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> })</tspan>
|
||||
<tspan x="10px" y="1612px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1630px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|__________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
<tspan x="10px" y="1630px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="1648px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="1648px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: the method `collect` exists for struct `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:29:8: 29:23}>>`, but its trait bounds were not satisfied</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1666px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)`</tspan>
|
||||
<tspan x="10px" y="1666px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:35:4</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1684px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: required for `(bool, HashSet<u8>)` to implement `IntoIterator`</tspan>
|
||||
<tspan x="10px" y="1684px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1702px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required by a bound in `Flatten`</tspan>
|
||||
<tspan x="10px" y="1702px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">/</tspan><tspan> hm.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1720px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL</tspan>
|
||||
<tspan x="10px" y="1720px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .map(|(is_true, ts)| {</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1738px">
|
||||
<tspan x="10px" y="1738px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> ts.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1756px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: the method `collect` exists for struct `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:29:8: 29:23}>>`, but its trait bounds were not satisfied</tspan>
|
||||
<tspan x="10px" y="1756px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .map(|t| (is_true, t))</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1774px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:35:4</tspan>
|
||||
<tspan x="10px" y="1774px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1792px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="1792px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1810px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">/</tspan><tspan> hm.into_iter()</tspan>
|
||||
<tspan x="10px" y="1810px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .collect()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1828px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .map(|(is_true, ts)| {</tspan>
|
||||
<tspan x="10px" y="1828px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">-</tspan><tspan class="fg-ansi256-009 bold">^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">method cannot be called due to unsatisfied trait bounds</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1846px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> ts.into_iter()</tspan>
|
||||
<tspan x="10px" y="1846px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1864px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .map(|t| (is_true, t))</tspan>
|
||||
<tspan x="10px" y="1864px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1882px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="1882px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1900px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .flatten()</tspan>
|
||||
<tspan x="10px" y="1900px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: the following trait bounds were not satisfied:</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1918px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .collect()</tspan>
|
||||
<tspan x="10px" y="1918px"><tspan> `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:29:8: 29:23}>>: Iterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1936px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">-</tspan><tspan class="fg-ansi256-009 bold">^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">method cannot be called due to unsatisfied trait bounds</tspan>
|
||||
<tspan x="10px" y="1936px"><tspan> which is required by `&mut Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:29:8: 29:23}>>: Iterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1954px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________|</tspan>
|
||||
<tspan x="10px" y="1954px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="1972px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="1972px"><tspan class="fg-ansi256-009 bold">error[E0277]</tspan><tspan class="bold">: `(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="1990px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="1990px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:43:7</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2008px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: the following trait bounds were not satisfied:</tspan>
|
||||
<tspan x="10px" y="2008px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2026px"><tspan> `<Flatten<Map<std::vec::IntoIter<HashSet<u8>>, {closure@$DIR/multiline-removal-suggestion.rs:31:10: 31:13}>> as IntoIterator>::IntoIter = _`</tspan>
|
||||
<tspan x="10px" y="2026px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> }).flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2044px"><tspan> which is required by `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:29:8: 29:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="2044px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2062px"><tspan> `<Flatten<Map<std::vec::IntoIter<HashSet<u8>>, {closure@$DIR/multiline-removal-suggestion.rs:31:10: 31:13}>> as IntoIterator>::Item = _`</tspan>
|
||||
<tspan x="10px" y="2062px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2080px"><tspan> which is required by `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:29:8: 29:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="2080px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2098px"><tspan> `Flatten<Map<std::vec::IntoIter<HashSet<u8>>, {closure@$DIR/multiline-removal-suggestion.rs:31:10: 31:13}>>: IntoIterator`</tspan>
|
||||
<tspan x="10px" y="2098px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: required for `(bool, HashSet<u8>)` to implement `IntoIterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2116px"><tspan> which is required by `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:29:8: 29:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="2116px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required by a bound in `flatten`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2134px"><tspan> `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:29:8: 29:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="2134px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2152px"><tspan> which is required by `&mut Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:29:8: 29:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="2152px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: consider removing this method call, as the receiver has type `std::vec::IntoIter<HashSet<u8>>` and `std::vec::IntoIter<HashSet<u8>>: Iterator` trivially holds</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2170px">
|
||||
<tspan x="10px" y="2170px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2188px"><tspan class="fg-ansi256-009 bold">error[E0277]</tspan><tspan class="bold">: `(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
<tspan x="10px" y="2188px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- </tspan><tspan> ts.into_iter()</tspan><tspan class="fg-ansi256-009">.map(|t| {</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2206px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:43:7</tspan>
|
||||
<tspan x="10px" y="2206px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- (is_true, t)</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2224px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="2224px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- })</tspan><tspan>.flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2242px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> }).flatten()</tspan>
|
||||
<tspan x="10px" y="2242px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-010">+ </tspan><tspan> ts.into_iter().flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2260px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
<tspan x="10px" y="2260px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2278px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="2278px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="2296px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)`</tspan>
|
||||
<tspan x="10px" y="2296px"><tspan class="fg-ansi256-009 bold">error[E0277]</tspan><tspan class="bold">: `(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2314px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: required for `(bool, HashSet<u8>)` to implement `IntoIterator`</tspan>
|
||||
<tspan x="10px" y="2314px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:39:2</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2332px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required by a bound in `flatten`</tspan>
|
||||
<tspan x="10px" y="2332px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2350px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL</tspan>
|
||||
<tspan x="10px" y="2350px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">/</tspan><tspan> hm.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2368px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: consider removing this method call, as the receiver has type `std::vec::IntoIter<HashSet<u8>>` and `std::vec::IntoIter<HashSet<u8>>: Iterator` trivially holds</tspan>
|
||||
<tspan x="10px" y="2368px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> .map(|(is_true, ts)| {</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2386px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="2386px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> ts.into_iter().map(|t| {</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2404px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- </tspan><tspan> ts.into_iter()</tspan><tspan class="fg-ansi256-009">.map(|t| {</tspan>
|
||||
<tspan x="10px" y="2404px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> (is_true, t)</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2422px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- (is_true, t)</tspan>
|
||||
<tspan x="10px" y="2422px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> }).flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2440px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- })</tspan><tspan>.flatten()</tspan>
|
||||
<tspan x="10px" y="2440px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> })</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2458px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-010">+ </tspan><tspan> ts.into_iter().flatten()</tspan>
|
||||
<tspan x="10px" y="2458px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|__________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2476px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2494px">
|
||||
<tspan x="10px" y="2494px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2512px"><tspan class="fg-ansi256-009 bold">error[E0277]</tspan><tspan class="bold">: `(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
<tspan x="10px" y="2512px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: required for `(bool, HashSet<u8>)` to implement `IntoIterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2530px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:39:2</tspan>
|
||||
<tspan x="10px" y="2530px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required by a bound in `Flatten`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2548px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="2548px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2566px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">/</tspan><tspan> hm.into_iter()</tspan>
|
||||
<tspan x="10px" y="2566px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="2584px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> .map(|(is_true, ts)| {</tspan>
|
||||
<tspan x="10px" y="2584px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: the method `collect` exists for struct `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:40:8: 40:23}>>`, but its trait bounds were not satisfied</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2602px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> ts.into_iter().map(|t| {</tspan>
|
||||
<tspan x="10px" y="2602px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:46:4</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2620px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> (is_true, t)</tspan>
|
||||
<tspan x="10px" y="2620px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2638px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> }).flatten()</tspan>
|
||||
<tspan x="10px" y="2638px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">/</tspan><tspan> hm.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2656px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> })</tspan>
|
||||
<tspan x="10px" y="2656px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .map(|(is_true, ts)| {</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2674px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|__________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
<tspan x="10px" y="2674px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> ts.into_iter().map(|t| {</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2692px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="2692px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> (is_true, t)</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2710px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)`</tspan>
|
||||
<tspan x="10px" y="2710px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2728px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: required for `(bool, HashSet<u8>)` to implement `IntoIterator`</tspan>
|
||||
<tspan x="10px" y="2728px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2746px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required by a bound in `Flatten`</tspan>
|
||||
<tspan x="10px" y="2746px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .collect()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2764px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL</tspan>
|
||||
<tspan x="10px" y="2764px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">-</tspan><tspan class="fg-ansi256-009 bold">^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">method cannot be called due to unsatisfied trait bounds</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2782px">
|
||||
<tspan x="10px" y="2782px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2800px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: the method `collect` exists for struct `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:40:8: 40:23}>>`, but its trait bounds were not satisfied</tspan>
|
||||
<tspan x="10px" y="2800px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2818px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:46:4</tspan>
|
||||
<tspan x="10px" y="2818px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2836px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="2836px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: the following trait bounds were not satisfied:</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2854px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">/</tspan><tspan> hm.into_iter()</tspan>
|
||||
<tspan x="10px" y="2854px"><tspan> `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:40:8: 40:23}>>: Iterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2872px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .map(|(is_true, ts)| {</tspan>
|
||||
<tspan x="10px" y="2872px"><tspan> which is required by `&mut Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:40:8: 40:23}>>: Iterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2890px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> ts.into_iter().map(|t| {</tspan>
|
||||
<tspan x="10px" y="2890px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="2908px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> (is_true, t)</tspan>
|
||||
<tspan x="10px" y="2908px"><tspan class="fg-ansi256-009 bold">error[E0277]</tspan><tspan class="bold">: `(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2926px"><tspan class="fg-ansi256-012 bold">...</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="2926px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:53:28</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2944px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .flatten()</tspan>
|
||||
<tspan x="10px" y="2944px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2962px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .collect()</tspan>
|
||||
<tspan x="10px" y="2962px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .map(|t| (is_true, t)).flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2980px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">-</tspan><tspan class="fg-ansi256-009 bold">^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">method cannot be called due to unsatisfied trait bounds</tspan>
|
||||
<tspan x="10px" y="2980px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="2998px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________|</tspan>
|
||||
<tspan x="10px" y="2998px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3016px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="3016px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3034px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="3034px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: required for `(bool, HashSet<u8>)` to implement `IntoIterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3052px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: the following trait bounds were not satisfied:</tspan>
|
||||
<tspan x="10px" y="3052px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required by a bound in `flatten`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3070px"><tspan> `<Flatten<Map<std::vec::IntoIter<HashSet<u8>>, {closure@$DIR/multiline-removal-suggestion.rs:41:23: 41:26}>> as IntoIterator>::IntoIter = _`</tspan>
|
||||
<tspan x="10px" y="3070px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3088px"><tspan> which is required by `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:40:8: 40:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="3088px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: consider removing this method call, as the receiver has type `std::vec::IntoIter<HashSet<u8>>` and `std::vec::IntoIter<HashSet<u8>>: Iterator` trivially holds</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3106px"><tspan> `<Flatten<Map<std::vec::IntoIter<HashSet<u8>>, {closure@$DIR/multiline-removal-suggestion.rs:41:23: 41:26}>> as IntoIterator>::Item = _`</tspan>
|
||||
<tspan x="10px" y="3106px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3124px"><tspan> which is required by `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:40:8: 40:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="3124px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- </tspan><tspan> ts.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3142px"><tspan> `Flatten<Map<std::vec::IntoIter<HashSet<u8>>, {closure@$DIR/multiline-removal-suggestion.rs:41:23: 41:26}>>: IntoIterator`</tspan>
|
||||
<tspan x="10px" y="3142px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- .map(|t| (is_true, t))</tspan><tspan>.flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3160px"><tspan> which is required by `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:40:8: 40:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="3160px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-010">+ </tspan><tspan> ts.into_iter().flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3178px"><tspan> `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:40:8: 40:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="3178px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3196px"><tspan> which is required by `&mut Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:40:8: 40:23}>>: Iterator`</tspan>
|
||||
<tspan x="10px" y="3196px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="3214px">
|
||||
<tspan x="10px" y="3214px"><tspan class="fg-ansi256-009 bold">error[E0277]</tspan><tspan class="bold">: `(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3232px"><tspan class="fg-ansi256-009 bold">error[E0277]</tspan><tspan class="bold">: `(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
<tspan x="10px" y="3232px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:50:2</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3250px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:53:28</tspan>
|
||||
<tspan x="10px" y="3250px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3268px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="3268px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">/</tspan><tspan> hm.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3286px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .map(|t| (is_true, t)).flatten()</tspan>
|
||||
<tspan x="10px" y="3286px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> .map(|(is_true, ts)| {</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3304px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
<tspan x="10px" y="3304px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> ts.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3322px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="3322px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> .map(|t| (is_true, t)).flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3340px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)`</tspan>
|
||||
<tspan x="10px" y="3340px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> })</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3358px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: required for `(bool, HashSet<u8>)` to implement `IntoIterator`</tspan>
|
||||
<tspan x="10px" y="3358px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|__________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3376px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required by a bound in `flatten`</tspan>
|
||||
<tspan x="10px" y="3376px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3394px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL</tspan>
|
||||
<tspan x="10px" y="3394px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3412px"><tspan class="fg-ansi256-014 bold">help</tspan><tspan>: consider removing this method call, as the receiver has type `std::vec::IntoIter<HashSet<u8>>` and `std::vec::IntoIter<HashSet<u8>>: Iterator` trivially holds</tspan>
|
||||
<tspan x="10px" y="3412px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: required for `(bool, HashSet<u8>)` to implement `IntoIterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3430px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="3430px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required by a bound in `Flatten`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3448px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- </tspan><tspan> ts.into_iter()</tspan>
|
||||
<tspan x="10px" y="3448px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3466px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-009">- .map(|t| (is_true, t))</tspan><tspan>.flatten()</tspan>
|
||||
<tspan x="10px" y="3466px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="3484px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-010">+ </tspan><tspan> ts.into_iter().flatten()</tspan>
|
||||
<tspan x="10px" y="3484px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: the method `collect` exists for struct `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:51:8: 51:23}>>`, but its trait bounds were not satisfied</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3502px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="3502px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:56:4</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3520px">
|
||||
<tspan x="10px" y="3520px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3538px"><tspan class="fg-ansi256-009 bold">error[E0277]</tspan><tspan class="bold">: `(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
<tspan x="10px" y="3538px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">/</tspan><tspan> hm.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3556px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:50:2</tspan>
|
||||
<tspan x="10px" y="3556px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .map(|(is_true, ts)| {</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3574px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="3574px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> ts.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3592px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">/</tspan><tspan> hm.into_iter()</tspan>
|
||||
<tspan x="10px" y="3592px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .map(|t| (is_true, t)).flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3610px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> .map(|(is_true, ts)| {</tspan>
|
||||
<tspan x="10px" y="3610px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> })</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3628px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> ts.into_iter()</tspan>
|
||||
<tspan x="10px" y="3628px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3646px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> .map(|t| (is_true, t)).flatten()</tspan>
|
||||
<tspan x="10px" y="3646px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .collect()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3664px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|</tspan><tspan> })</tspan>
|
||||
<tspan x="10px" y="3664px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">-</tspan><tspan class="fg-ansi256-009 bold">^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">method cannot be called due to unsatisfied trait bounds</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3682px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">|__________^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">`(bool, HashSet<u8>)` is not an iterator</tspan>
|
||||
<tspan x="10px" y="3682px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3700px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3718px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">help</tspan><tspan>: the trait `Iterator` is not implemented for `(bool, HashSet<u8>)`</tspan>
|
||||
<tspan x="10px" y="3718px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3736px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: required for `(bool, HashSet<u8>)` to implement `IntoIterator`</tspan>
|
||||
<tspan x="10px" y="3736px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: the following trait bounds were not satisfied:</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3754px"><tspan class="fg-ansi256-010 bold">note</tspan><tspan>: required by a bound in `Flatten`</tspan>
|
||||
<tspan x="10px" y="3754px"><tspan> `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:51:8: 51:23}>>: Iterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3772px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL</tspan>
|
||||
<tspan x="10px" y="3772px"><tspan> which is required by `&mut Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:51:8: 51:23}>>: Iterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3790px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="3808px"><tspan class="fg-ansi256-009 bold">error[E0599]</tspan><tspan class="bold">: the method `collect` exists for struct `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:51:8: 51:23}>>`, but its trait bounds were not satisfied</tspan>
|
||||
<tspan x="10px" y="3808px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 12 previous errors</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3826px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">--> </tspan><tspan>$DIR/multiline-removal-suggestion.rs:56:4</tspan>
|
||||
<tspan x="10px" y="3826px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="3844px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
<tspan x="10px" y="3844px"><tspan class="bold">Some errors have detailed explanations: E0277, E0599.</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3862px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">/</tspan><tspan> hm.into_iter()</tspan>
|
||||
<tspan x="10px" y="3862px"><tspan class="bold">For more information about an error, try `rustc --explain E0277`.</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3880px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .map(|(is_true, ts)| {</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3898px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> ts.into_iter()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3916px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .map(|t| (is_true, t)).flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3934px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> })</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3952px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .flatten()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3970px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> .collect()</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="3988px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">-</tspan><tspan class="fg-ansi256-009 bold">^^^^^^^</tspan><tspan> </tspan><tspan class="fg-ansi256-009 bold">method cannot be called due to unsatisfied trait bounds</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4006px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|_________|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4024px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4042px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4060px"><tspan> </tspan><tspan class="fg-ansi256-012 bold">= </tspan><tspan class="bold">note</tspan><tspan>: the following trait bounds were not satisfied:</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4078px"><tspan> `<Flatten<Map<std::vec::IntoIter<HashSet<u8>>, {closure@$DIR/multiline-removal-suggestion.rs:53:10: 53:13}>> as IntoIterator>::IntoIter = _`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4096px"><tspan> which is required by `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:51:8: 51:23}>>: Iterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4114px"><tspan> `<Flatten<Map<std::vec::IntoIter<HashSet<u8>>, {closure@$DIR/multiline-removal-suggestion.rs:53:10: 53:13}>> as IntoIterator>::Item = _`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4132px"><tspan> which is required by `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:51:8: 51:23}>>: Iterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4150px"><tspan> `Flatten<Map<std::vec::IntoIter<HashSet<u8>>, {closure@$DIR/multiline-removal-suggestion.rs:53:10: 53:13}>>: IntoIterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4168px"><tspan> which is required by `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:51:8: 51:23}>>: Iterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4186px"><tspan> `Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:51:8: 51:23}>>: Iterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4204px"><tspan> which is required by `&mut Flatten<Map<std::collections::hash_map::IntoIter<bool, Vec<HashSet<u8>>>, {closure@$DIR/multiline-removal-suggestion.rs:51:8: 51:23}>>: Iterator`</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4222px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="4240px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 12 previous errors</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4258px">
|
||||
</tspan>
|
||||
<tspan x="10px" y="4276px"><tspan class="bold">Some errors have detailed explanations: E0277, E0599.</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4294px"><tspan class="bold">For more information about an error, try `rustc --explain E0277`.</tspan>
|
||||
</tspan>
|
||||
<tspan x="10px" y="4312px">
|
||||
<tspan x="10px" y="3880px">
|
||||
</tspan>
|
||||
</text>
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 40 KiB |
|
|
@ -1,14 +1,24 @@
|
|||
error[E0282]: type annotations needed
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:19:17
|
||||
error[E0282]: type annotations needed for `(_,)`
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:19:9
|
||||
|
|
||||
LL | let (x,) = (build(x),);
|
||||
| ^^^^^^^^ cannot infer type
|
||||
| ^^^^
|
||||
|
|
||||
help: consider giving this pattern a type, where the placeholders `_` are specified
|
||||
|
|
||||
LL | let (x,): (_,) = (build(x),);
|
||||
| ++++++
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:29:17
|
||||
error[E0282]: type annotations needed for `((_,),)`
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:29:9
|
||||
|
|
||||
LL | let (x,) = (build2(x),);
|
||||
| ^^^^^^^^^ cannot infer type
|
||||
| ^^^^
|
||||
|
|
||||
help: consider giving this pattern a type, where the placeholders `_` are specified
|
||||
|
|
||||
LL | let (x,): ((_,),) = (build2(x),);
|
||||
| +++++++++
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/recursive-in-exhaustiveness.rs:40:5
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
// Tests that we correctly handle opaque types being used opaquely,
|
||||
// even within their defining scope.
|
||||
//
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
type Foo = impl Copy;
|
||||
|
||||
enum Wrapper<T> {
|
||||
First(T),
|
||||
Second,
|
||||
}
|
||||
|
||||
// This method constrains `Foo` to be `bool`
|
||||
#[define_opaque(Foo)]
|
||||
fn constrained_foo() -> Foo {
|
||||
true
|
||||
}
|
||||
|
||||
// This method does not constrain `Foo`.
|
||||
// Per RFC 2071, function bodies may either
|
||||
// fully constrain an opaque type, or place no
|
||||
// constraints on it.
|
||||
#[define_opaque(Foo)]
|
||||
fn unconstrained_foo() -> Wrapper<Foo> {
|
||||
Wrapper::Second
|
||||
//~^ ERROR: type annotations needed
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
error[E0283]: type annotations needed
|
||||
--> $DIR/fallback.rs:25:5
|
||||
|
|
||||
LL | fn unconstrained_foo() -> Wrapper<Foo> {
|
||||
| ------------ type must be known at this point
|
||||
LL | Wrapper::Second
|
||||
| ^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| cannot infer type of the type parameter `T` declared on the enum `Wrapper`
|
||||
| return type was inferred to be `Wrapper<_>` here
|
||||
|
|
||||
= note: cannot satisfy `_: Copy`
|
||||
help: consider specifying the generic argument
|
||||
|
|
||||
LL | Wrapper::<T>::Second
|
||||
| +++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue