mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Rollup merge of #154257 - jdonszelmann:revert-eagerly-normalize-in-generalize, r=lcnr
Revert eagerly normalize in generalize r? @lcnr Reverts https://github.com/rust-lang/rust/pull/151746 We'll likely pull eager normalization out of generalization Fixes rust-lang/rust#154173 Fixes rust-lang/rust#154244
This commit is contained in:
@@ -616,9 +616,4 @@ fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
|
||||
}
|
||||
})]);
|
||||
}
|
||||
|
||||
fn try_eagerly_normalize_alias(&mut self, _alias: ty::AliasTy<'tcx>) -> Ty<'tcx> {
|
||||
// Past hir typeck, so we don't have to worry about type inference anymore.
|
||||
self.type_checker.infcx.next_ty_var(self.span())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,9 +140,6 @@ pub fn sup<T>(
|
||||
ty::Contravariant,
|
||||
actual,
|
||||
self.cause.span,
|
||||
&mut |alias| {
|
||||
self.infcx.try_eagerly_normalize_alias(self.param_env, self.cause.span, alias)
|
||||
},
|
||||
)
|
||||
.map(|goals| self.goals_to_obligations(goals))
|
||||
} else {
|
||||
@@ -176,9 +173,6 @@ pub fn sub<T>(
|
||||
ty::Covariant,
|
||||
actual,
|
||||
self.cause.span,
|
||||
&mut |alias| {
|
||||
self.infcx.try_eagerly_normalize_alias(self.param_env, self.cause.span, alias)
|
||||
},
|
||||
)
|
||||
.map(|goals| self.goals_to_obligations(goals))
|
||||
} else {
|
||||
@@ -231,9 +225,6 @@ pub fn eq_trace<T>(
|
||||
ty::Invariant,
|
||||
actual,
|
||||
self.cause.span,
|
||||
&mut |alias| {
|
||||
self.infcx.try_eagerly_normalize_alias(self.param_env, self.cause.span, alias)
|
||||
},
|
||||
)
|
||||
.map(|goals| self.goals_to_obligations(goals))
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::{fmt, mem};
|
||||
use std::fmt;
|
||||
|
||||
pub use at::DefineOpaqueTypes;
|
||||
use free_regions::RegionRelations;
|
||||
@@ -21,7 +21,6 @@
|
||||
use rustc_macros::extension;
|
||||
pub use rustc_macros::{TypeFoldable, TypeVisitable};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::hooks::TypeErasedInfcx;
|
||||
use rustc_middle::infer::canonical::{CanonicalQueryInput, CanonicalVarValues};
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::traits::select;
|
||||
@@ -1529,17 +1528,6 @@ pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar) -> boo
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_eagerly_normalize_alias<'a>(
|
||||
&'a self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
span: Span,
|
||||
alias: ty::AliasTy<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let erased =
|
||||
unsafe { mem::transmute::<&'a InferCtxt<'tcx>, TypeErasedInfcx<'a, 'tcx>>(self) };
|
||||
self.tcx.try_eagerly_normalize_alias(erased, param_env, span, alias)
|
||||
}
|
||||
|
||||
/// Attach a callback to be invoked on each root obligation evaluated in the new trait solver.
|
||||
pub fn attach_obligation_inspector(&self, inspector: ObligationInspector<'tcx>) {
|
||||
debug_assert!(
|
||||
|
||||
@@ -51,7 +51,7 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
/// `TypeRelation`. Do not use this, and instead please use `At::eq`, for all
|
||||
/// other usecases (i.e. setting the value of a type var).
|
||||
#[instrument(level = "debug", skip(self, relation))]
|
||||
pub fn instantiate_ty_var<R: PredicateEmittingRelation<Self>>(
|
||||
pub fn instantiate_ty_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
|
||||
&self,
|
||||
relation: &mut R,
|
||||
target_is_expected: bool,
|
||||
@@ -61,56 +61,29 @@ pub fn instantiate_ty_var<R: PredicateEmittingRelation<Self>>(
|
||||
) -> RelateResult<'tcx, ()> {
|
||||
debug_assert!(self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown());
|
||||
|
||||
let generalized_ty = if self.next_trait_solver()
|
||||
&& matches!(relation.structurally_relate_aliases(), StructurallyRelateAliases::No)
|
||||
&& let ty::Alias(_, alias) = source_ty.kind()
|
||||
{
|
||||
let normalized_alias = relation.try_eagerly_normalize_alias(*alias);
|
||||
// Generalize `source_ty` depending on the current variance. As an example, assume
|
||||
// `?target <: &'x ?1`, where `'x` is some free region and `?1` is an inference
|
||||
// variable.
|
||||
//
|
||||
// Then the `generalized_ty` would be `&'?2 ?3`, where `'?2` and `?3` are fresh
|
||||
// region/type inference variables.
|
||||
//
|
||||
// We then relate `generalized_ty <: source_ty`, adding constraints like `'x: '?2` and
|
||||
// `?1 <: ?3`.
|
||||
let Generalization { value_may_be_infer: generalized_ty } = self.generalize(
|
||||
relation.span(),
|
||||
relation.structurally_relate_aliases(),
|
||||
target_vid,
|
||||
instantiation_variance,
|
||||
source_ty,
|
||||
)?;
|
||||
|
||||
if normalized_alias.is_ty_var() {
|
||||
normalized_alias
|
||||
} else {
|
||||
let Generalization { value_may_be_infer: generalized_ty } = self.generalize(
|
||||
relation.span(),
|
||||
GeneralizerState::ShallowStructurallyRelateAliases,
|
||||
target_vid,
|
||||
instantiation_variance,
|
||||
normalized_alias,
|
||||
&mut |alias| relation.try_eagerly_normalize_alias(alias),
|
||||
)?;
|
||||
|
||||
// The only way to get a tyvar back is if the outermost type is an alias.
|
||||
// However, here, though we know it *is* an alias, we initialize the generalizer
|
||||
// with `ShallowStructurallyRelateAliases` so we treat the outermost alias as rigid,
|
||||
// ensuring this is never a tyvar.
|
||||
assert!(!generalized_ty.is_ty_var());
|
||||
|
||||
generalized_ty
|
||||
}
|
||||
// Constrain `b_vid` to the generalized type `generalized_ty`.
|
||||
if let &ty::Infer(ty::TyVar(generalized_vid)) = generalized_ty.kind() {
|
||||
self.inner.borrow_mut().type_variables().equate(target_vid, generalized_vid);
|
||||
} else {
|
||||
// Generalize `source_ty` depending on the current variance. As an example, assume
|
||||
// `?target <: &'x ?1`, where `'x` is some free region and `?1` is an inference
|
||||
// variable.
|
||||
//
|
||||
// Then the `generalized_ty` would be `&'?2 ?3`, where `'?2` and `?3` are fresh
|
||||
// region/type inference variables.
|
||||
//
|
||||
// We then relate `generalized_ty <: source_ty`, adding constraints like `'x: '?2` and
|
||||
// `?1 <: ?3`.
|
||||
let Generalization { value_may_be_infer: generalized_ty } = self.generalize(
|
||||
relation.span(),
|
||||
match relation.structurally_relate_aliases() {
|
||||
StructurallyRelateAliases::No => GeneralizerState::Default,
|
||||
StructurallyRelateAliases::Yes => GeneralizerState::StructurallyRelateAliases,
|
||||
},
|
||||
target_vid,
|
||||
instantiation_variance,
|
||||
source_ty,
|
||||
&mut |alias| relation.try_eagerly_normalize_alias(alias),
|
||||
)?;
|
||||
|
||||
generalized_ty
|
||||
};
|
||||
self.inner.borrow_mut().type_variables().instantiate(target_vid, generalized_ty);
|
||||
}
|
||||
|
||||
// Finally, relate `generalized_ty` to `source_ty`, as described in previous comment.
|
||||
//
|
||||
@@ -118,10 +91,7 @@ pub fn instantiate_ty_var<R: PredicateEmittingRelation<Self>>(
|
||||
// relations wind up attributed to the same spans. We need
|
||||
// to associate causes/spans with each of the relations in
|
||||
// the stack to get this right.
|
||||
if let &ty::Infer(ty::TyVar(generalized_vid)) = generalized_ty.kind() {
|
||||
// Constrain `b_vid` to the generalized type variable.
|
||||
self.inner.borrow_mut().type_variables().equate(target_vid, generalized_vid);
|
||||
|
||||
if generalized_ty.is_ty_var() {
|
||||
// This happens for cases like `<?0 as Trait>::Assoc == ?0`.
|
||||
// We can't instantiate `?0` here as that would result in a
|
||||
// cyclic type. We instead delay the unification in case
|
||||
@@ -162,9 +132,6 @@ pub fn instantiate_ty_var<R: PredicateEmittingRelation<Self>>(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Constrain `b_vid` to the generalized type `generalized_ty`.
|
||||
self.inner.borrow_mut().type_variables().instantiate(target_vid, generalized_ty);
|
||||
|
||||
// NOTE: The `instantiation_variance` is not the same variance as
|
||||
// used by the relation. When instantiating `b`, `target_is_expected`
|
||||
// is flipped and the `instantiation_variance` is also flipped. To
|
||||
@@ -239,14 +206,10 @@ pub(crate) fn instantiate_const_var<R: PredicateEmittingRelation<InferCtxt<'tcx>
|
||||
// constants and generic expressions are not yet handled correctly.
|
||||
let Generalization { value_may_be_infer: generalized_ct } = self.generalize(
|
||||
relation.span(),
|
||||
match relation.structurally_relate_aliases() {
|
||||
StructurallyRelateAliases::No => GeneralizerState::Default,
|
||||
StructurallyRelateAliases::Yes => GeneralizerState::StructurallyRelateAliases,
|
||||
},
|
||||
relation.structurally_relate_aliases(),
|
||||
target_vid,
|
||||
ty::Invariant,
|
||||
source_ct,
|
||||
&mut |alias| relation.try_eagerly_normalize_alias(alias),
|
||||
)?;
|
||||
|
||||
debug_assert!(!generalized_ct.is_ct_infer());
|
||||
@@ -282,11 +245,10 @@ pub(crate) fn instantiate_const_var<R: PredicateEmittingRelation<InferCtxt<'tcx>
|
||||
fn generalize<T: Into<Term<'tcx>> + Relate<TyCtxt<'tcx>>>(
|
||||
&self,
|
||||
span: Span,
|
||||
initial_state: GeneralizerState,
|
||||
structurally_relate_aliases: StructurallyRelateAliases,
|
||||
target_vid: impl Into<TermVid>,
|
||||
ambient_variance: ty::Variance,
|
||||
source_term: T,
|
||||
normalize: &mut dyn FnMut(ty::AliasTy<'tcx>) -> Ty<'tcx>,
|
||||
) -> RelateResult<'tcx, Generalization<T>> {
|
||||
assert!(!source_term.has_escaping_bound_vars());
|
||||
let (for_universe, root_vid) = match target_vid.into() {
|
||||
@@ -302,13 +264,13 @@ fn generalize<T: Into<Term<'tcx>> + Relate<TyCtxt<'tcx>>>(
|
||||
let mut generalizer = Generalizer {
|
||||
infcx: self,
|
||||
span,
|
||||
structurally_relate_aliases,
|
||||
root_vid,
|
||||
for_universe,
|
||||
root_term: source_term.into(),
|
||||
ambient_variance,
|
||||
state: initial_state,
|
||||
in_alias: false,
|
||||
cache: Default::default(),
|
||||
normalize,
|
||||
};
|
||||
|
||||
let value_may_be_infer = generalizer.relate(source_term, source_term)?;
|
||||
@@ -355,54 +317,6 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) {
|
||||
}
|
||||
}
|
||||
|
||||
/// This state determines how generalization treats aliases.
|
||||
///
|
||||
/// Based on which state we're in, we treat them either as rigid or normalizable,
|
||||
/// which might change depending on what types the generalization visitor encounters.
|
||||
/// See `handle_alias_ty` for the logic of how we change states.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
enum GeneralizerState {
|
||||
/// Treat aliases as potentially normalizable.
|
||||
///
|
||||
/// This is the default state that generalization starts in, unless we're
|
||||
/// treating aliases as rigid. It also means we're not currently inside an
|
||||
/// alias, since then we change the state to `IncompletelyRelateAliasArgs`.
|
||||
Default,
|
||||
/// We enter this state when we're generalizing the arguments of a
|
||||
/// potentially normalizeable alias.
|
||||
///
|
||||
/// The behavior here is different between the old and the new solver:
|
||||
///
|
||||
/// In the old solver, the difference between this and `Default` is needed to
|
||||
/// correctly handle `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. That
|
||||
/// equality can hold by either normalizing the outer or the inner
|
||||
/// associated type. In the old solver, we always structurally relate
|
||||
/// aliases. If we we encounter an occurs check failure, we propagate the
|
||||
/// failure to the outermost alias, for which we then emit a `Projection`
|
||||
/// goal instead.
|
||||
///
|
||||
/// In the new solver, we rarely get into this state.
|
||||
/// When we encounter aliases we instead attempt to normalize them, and treat
|
||||
/// them as rigid using `ShallowStructurallyRelate`. Only when an alias has
|
||||
/// escaping bound variables do we continue with similar logic to the old
|
||||
/// solver, except now we also explicitly relate the type and consts in the
|
||||
/// arguments of aliases while in this mode.
|
||||
///
|
||||
/// FIXME: Because we relate the type and consts in the arguments of aliases
|
||||
/// while in this mode, this is incomplete.
|
||||
IncompletelyRelateAliasArgs,
|
||||
/// During generalization, when we encounter aliases, we will first attempt
|
||||
/// to normalize them when we're using the next trait solver. We can now
|
||||
/// treat the normalized alias as rigid, but only for "one layer", hence
|
||||
/// shallow. New aliases encountered inside the arguments of the outer alias
|
||||
/// should once again be related as normal.
|
||||
ShallowStructurallyRelateAliases,
|
||||
/// Treat aliases as rigid when relating them.
|
||||
///
|
||||
/// This corresponds to `relation.structurally_relate_aliases()`.
|
||||
StructurallyRelateAliases,
|
||||
}
|
||||
|
||||
/// The "generalizer" is used when handling inference variables.
|
||||
///
|
||||
/// The basic strategy for handling a constraint like `?A <: B` is to
|
||||
@@ -421,6 +335,10 @@ struct Generalizer<'me, 'tcx> {
|
||||
|
||||
span: Span,
|
||||
|
||||
/// Whether aliases should be related structurally. If not, we have to
|
||||
/// be careful when generalizing aliases.
|
||||
structurally_relate_aliases: StructurallyRelateAliases,
|
||||
|
||||
/// The vid of the type variable that is in the process of being
|
||||
/// instantiated. If we find this within the value we are folding,
|
||||
/// that means we would have created a cyclic value.
|
||||
@@ -438,17 +356,14 @@ struct Generalizer<'me, 'tcx> {
|
||||
/// some other type. What will be the variance at this point?
|
||||
ambient_variance: ty::Variance,
|
||||
|
||||
/// This field keeps track of how we treat aliases during generalization.
|
||||
/// This is set once we're generalizing the arguments of an alias.
|
||||
///
|
||||
/// Refer to [`GeneralizerState`]'s docs for more information about the
|
||||
/// all the possible values this can have, and when we use which.
|
||||
state: GeneralizerState,
|
||||
/// This is necessary to correctly handle
|
||||
/// `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. This equality can
|
||||
/// hold by either normalizing the outer or the inner associated type.
|
||||
in_alias: bool,
|
||||
|
||||
cache: SsoHashMap<(Ty<'tcx>, ty::Variance, GeneralizerState), Ty<'tcx>>,
|
||||
|
||||
/// Normalize an alias in the trait solver.
|
||||
/// If normalization fails, a fresh infer var is returned.
|
||||
normalize: &'me mut dyn FnMut(ty::AliasTy<'tcx>) -> Ty<'tcx>,
|
||||
cache: SsoHashMap<(Ty<'tcx>, ty::Variance, bool), Ty<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> Generalizer<'_, 'tcx> {
|
||||
@@ -484,51 +399,27 @@ fn next_ty_var_for_alias(&self) -> Ty<'tcx> {
|
||||
/// continue generalizing the alias. This ends up pulling down the universe of the
|
||||
/// inference variable and is incomplete in case the alias would normalize to a type
|
||||
/// which does not mention that inference variable.
|
||||
fn handle_alias_ty(
|
||||
fn generalize_alias_ty(
|
||||
&mut self,
|
||||
alias_ty: Ty<'tcx>,
|
||||
alias: ty::AliasTy<'tcx>,
|
||||
) -> Result<Ty<'tcx>, TypeError<'tcx>> {
|
||||
match self.state {
|
||||
GeneralizerState::ShallowStructurallyRelateAliases => {
|
||||
// We can switch back to default, we've treated one layer as rigid by doing this operation.
|
||||
self.state = GeneralizerState::Default;
|
||||
let res = relate::structurally_relate_tys(self, alias_ty, alias_ty);
|
||||
self.state = GeneralizerState::ShallowStructurallyRelateAliases;
|
||||
return res;
|
||||
}
|
||||
GeneralizerState::StructurallyRelateAliases => {
|
||||
return relate::structurally_relate_tys(self, alias_ty, alias_ty);
|
||||
}
|
||||
GeneralizerState::Default
|
||||
if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() =>
|
||||
{
|
||||
// We do not eagerly replace aliases with inference variables if they have
|
||||
// escaping bound vars, see the method comment for details. However, when we
|
||||
// are inside of an alias with escaping bound vars replacing nested aliases
|
||||
// with inference variables can cause incorrect ambiguity.
|
||||
//
|
||||
// cc trait-system-refactor-initiative#110
|
||||
let normalized_alias = (self.normalize)(alias);
|
||||
|
||||
self.state = GeneralizerState::ShallowStructurallyRelateAliases;
|
||||
// recursively generalize, treat the outer alias as rigid to avoid infinite recursion
|
||||
let res = self.relate(normalized_alias, normalized_alias);
|
||||
|
||||
// only one way to get here
|
||||
self.state = GeneralizerState::Default;
|
||||
|
||||
return res;
|
||||
}
|
||||
GeneralizerState::Default | GeneralizerState::IncompletelyRelateAliasArgs => {}
|
||||
// We do not eagerly replace aliases with inference variables if they have
|
||||
// escaping bound vars, see the method comment for details. However, when we
|
||||
// are inside of an alias with escaping bound vars replacing nested aliases
|
||||
// with inference variables can cause incorrect ambiguity.
|
||||
//
|
||||
// cc trait-system-refactor-initiative#110
|
||||
if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() && !self.in_alias {
|
||||
return Ok(self.next_ty_var_for_alias());
|
||||
}
|
||||
|
||||
let previous_state =
|
||||
mem::replace(&mut self.state, GeneralizerState::IncompletelyRelateAliasArgs);
|
||||
let is_nested_alias = mem::replace(&mut self.in_alias, true);
|
||||
let result = match self.relate(alias, alias) {
|
||||
Ok(alias) => Ok(alias.to_ty(self.cx())),
|
||||
Err(e) => match previous_state {
|
||||
GeneralizerState::Default => {
|
||||
Err(e) => {
|
||||
if is_nested_alias {
|
||||
return Err(e);
|
||||
} else {
|
||||
let mut visitor = MaxUniverse::new();
|
||||
alias.visit_with(&mut visitor);
|
||||
let infer_replacement_is_complete =
|
||||
@@ -541,14 +432,9 @@ fn handle_alias_ty(
|
||||
debug!("generalization failure in alias");
|
||||
Ok(self.next_ty_var_for_alias())
|
||||
}
|
||||
GeneralizerState::IncompletelyRelateAliasArgs => return Err(e),
|
||||
|
||||
// Early return.
|
||||
GeneralizerState::ShallowStructurallyRelateAliases
|
||||
| GeneralizerState::StructurallyRelateAliases => unreachable!(),
|
||||
},
|
||||
}
|
||||
};
|
||||
self.state = previous_state;
|
||||
self.in_alias = is_nested_alias;
|
||||
result
|
||||
}
|
||||
}
|
||||
@@ -602,7 +488,7 @@ fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
|
||||
fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
|
||||
|
||||
if let Some(&result) = self.cache.get(&(t, self.ambient_variance, self.state)) {
|
||||
if let Some(&result) = self.cache.get(&(t, self.ambient_variance, self.in_alias)) {
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
@@ -650,7 +536,6 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
// 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.
|
||||
@@ -668,15 +553,9 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
// cc trait-system-refactor-initiative#108
|
||||
if self.infcx.next_trait_solver()
|
||||
&& !matches!(self.infcx.typing_mode(), TypingMode::Coherence)
|
||||
&& self.in_alias
|
||||
{
|
||||
match self.state {
|
||||
GeneralizerState::IncompletelyRelateAliasArgs => {
|
||||
inner.type_variables().equate(vid, new_var_id);
|
||||
}
|
||||
GeneralizerState::Default
|
||||
| GeneralizerState::ShallowStructurallyRelateAliases
|
||||
| GeneralizerState::StructurallyRelateAliases => {}
|
||||
}
|
||||
inner.type_variables().equate(vid, new_var_id);
|
||||
}
|
||||
|
||||
debug!("replacing original vid={:?} with new={:?}", vid, new_var_id);
|
||||
@@ -705,12 +584,15 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
}
|
||||
}
|
||||
|
||||
ty::Alias(_, data) => self.handle_alias_ty(t, data),
|
||||
ty::Alias(_, data) => match self.structurally_relate_aliases {
|
||||
StructurallyRelateAliases::No => self.generalize_alias_ty(data),
|
||||
StructurallyRelateAliases::Yes => relate::structurally_relate_tys(self, t, t),
|
||||
},
|
||||
|
||||
_ => relate::structurally_relate_tys(self, t, t),
|
||||
}?;
|
||||
|
||||
self.cache.insert((t, self.ambient_variance, self.state), g);
|
||||
self.cache.insert((t, self.ambient_variance, self.in_alias), g);
|
||||
Ok(g)
|
||||
}
|
||||
|
||||
@@ -801,15 +683,9 @@ fn consts(
|
||||
// for more details.
|
||||
if self.infcx.next_trait_solver()
|
||||
&& !matches!(self.infcx.typing_mode(), TypingMode::Coherence)
|
||||
&& self.in_alias
|
||||
{
|
||||
match self.state {
|
||||
GeneralizerState::IncompletelyRelateAliasArgs => {
|
||||
variable_table.union(vid, new_var_id);
|
||||
}
|
||||
GeneralizerState::Default
|
||||
| GeneralizerState::ShallowStructurallyRelateAliases
|
||||
| GeneralizerState::StructurallyRelateAliases => {}
|
||||
}
|
||||
variable_table.union(vid, new_var_id);
|
||||
}
|
||||
Ok(ty::Const::new_var(self.cx(), new_var_id))
|
||||
}
|
||||
|
||||
@@ -299,8 +299,4 @@ fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
|
||||
ty::AliasRelationDirection::Equate,
|
||||
))]);
|
||||
}
|
||||
|
||||
fn try_eagerly_normalize_alias(&mut self, alias: ty::AliasTy<'tcx>) -> Ty<'tcx> {
|
||||
self.infcx.try_eagerly_normalize_alias(self.param_env(), self.span(), alias)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,13 +396,4 @@ fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
|
||||
}
|
||||
})]);
|
||||
}
|
||||
|
||||
fn try_eagerly_normalize_alias(
|
||||
&mut self,
|
||||
_alias: rustc_type_ir::AliasTy<<InferCtxt<'tcx> as rustc_type_ir::InferCtxtLike>::Interner>,
|
||||
) -> <<InferCtxt<'tcx> as rustc_type_ir::InferCtxtLike>::Interner as rustc_type_ir::Interner>::Ty
|
||||
{
|
||||
// We only try to eagerly normalize aliases if we're using the new solver.
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -904,7 +904,7 @@ pub fn write_interface<'tcx>(tcx: TyCtxt<'tcx>) {
|
||||
rustc_hir_typeck::provide(&mut providers.queries);
|
||||
ty::provide(&mut providers.queries);
|
||||
traits::provide(&mut providers.queries);
|
||||
solve::provide(providers);
|
||||
solve::provide(&mut providers.queries);
|
||||
rustc_passes::provide(&mut providers.queries);
|
||||
rustc_traits::provide(&mut providers.queries);
|
||||
rustc_ty_utils::provide(&mut providers.queries);
|
||||
|
||||
@@ -3,16 +3,14 @@
|
||||
//! similar to queries, but queries come with a lot of machinery for caching and incremental
|
||||
//! compilation, whereas hooks are just plain function pointers without any of the query magic.
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use rustc_hir::def_id::{DefId, DefPathHash};
|
||||
use rustc_session::StableCrateId;
|
||||
use rustc_span::def_id::{CrateNum, LocalDefId};
|
||||
use rustc_span::{ExpnHash, ExpnId, Span};
|
||||
use rustc_span::{ExpnHash, ExpnId};
|
||||
|
||||
use crate::mir;
|
||||
use crate::query::on_disk_cache::{CacheEncoder, EncodedDepNodeIndex};
|
||||
use crate::ty::{Ty, TyCtxt};
|
||||
use crate::{mir, ty};
|
||||
|
||||
macro_rules! declare_hooks {
|
||||
($($(#[$attr:meta])*hook $name:ident($($arg:ident: $K:ty),*) -> $V:ty;)*) => {
|
||||
@@ -117,29 +115,6 @@ fn clone(&self) -> Self { *self }
|
||||
encoder: &mut CacheEncoder<'_, 'tcx>,
|
||||
query_result_index: &mut EncodedDepNodeIndex
|
||||
) -> ();
|
||||
|
||||
/// Tries to normalize an alias, ignoring any errors.
|
||||
///
|
||||
/// Generalization with the new trait solver calls into this,
|
||||
/// when generalizing outside of the trait solver in `hir_typeck`.
|
||||
hook try_eagerly_normalize_alias(
|
||||
type_erased_infcx: TypeErasedInfcx<'_, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
span: Span,
|
||||
alias: ty::AliasTy<'tcx>
|
||||
) -> Ty<'tcx>;
|
||||
}
|
||||
|
||||
/// The `try_eagerly_normalize_alias` hook passes an `Infcx` from where it's called (in `rustc_infer`)
|
||||
/// to where it's provided (in `rustc_trait_selection`).
|
||||
/// Both of those crates have that type available, but `rustc_middle` does not.
|
||||
/// Instead we pass this type-erased `Infcx` and transmute on both sides.
|
||||
///
|
||||
/// Has to be `repr(transparent)` so we can transmute a `&'a Infcx<'tcx>` to this struct.
|
||||
#[repr(transparent)]
|
||||
pub struct TypeErasedInfcx<'a, 'tcx> {
|
||||
_infcx: *const (),
|
||||
phantom: PhantomData<&'a mut &'tcx ()>,
|
||||
}
|
||||
|
||||
#[cold]
|
||||
|
||||
@@ -177,11 +177,7 @@ fn canonicalize_param_env(
|
||||
cache: Default::default(),
|
||||
};
|
||||
let param_env = param_env.fold_with(&mut env_canonicalizer);
|
||||
debug_assert!(
|
||||
env_canonicalizer.sub_root_lookup_table.is_empty(),
|
||||
"{:?}",
|
||||
env_canonicalizer.sub_root_lookup_table
|
||||
);
|
||||
debug_assert!(env_canonicalizer.sub_root_lookup_table.is_empty());
|
||||
(
|
||||
param_env,
|
||||
env_canonicalizer.variables,
|
||||
|
||||
@@ -987,12 +987,7 @@ fn try_eagerly_replace_alias(
|
||||
let replacement = self.ecx.instantiate_binder_with_infer(*replacement);
|
||||
self.nested.extend(
|
||||
self.ecx
|
||||
.relate_and_get_goals(
|
||||
self.param_env,
|
||||
alias_term,
|
||||
ty::Invariant,
|
||||
replacement.projection_term,
|
||||
)
|
||||
.eq_and_get_goals(self.param_env, alias_term, replacement.projection_term)
|
||||
.expect("expected to be able to unify goal projection with dyn's projection"),
|
||||
);
|
||||
|
||||
|
||||
@@ -408,7 +408,7 @@ pub(super) fn ignore_candidate_head_usages(&mut self, usages: CandidateHeadUsage
|
||||
|
||||
/// Recursively evaluates `goal`, returning whether any inference vars have
|
||||
/// been constrained and the certainty of the result.
|
||||
pub(super) fn evaluate_goal(
|
||||
fn evaluate_goal(
|
||||
&mut self,
|
||||
source: GoalSource,
|
||||
goal: Goal<I, I::Predicate>,
|
||||
@@ -1018,8 +1018,7 @@ pub(super) fn relate<T: Relate<I>>(
|
||||
variance: ty::Variance,
|
||||
rhs: T,
|
||||
) -> Result<(), NoSolution> {
|
||||
let goals = self.relate_and_get_goals(param_env, lhs, variance, rhs)?;
|
||||
|
||||
let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?;
|
||||
for &goal in goals.iter() {
|
||||
let source = match goal.predicate.kind().skip_binder() {
|
||||
ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => {
|
||||
@@ -1040,37 +1039,13 @@ pub(super) fn relate<T: Relate<I>>(
|
||||
/// If possible, try using `eq` instead which automatically handles nested
|
||||
/// goals correctly.
|
||||
#[instrument(level = "trace", skip(self, param_env), ret)]
|
||||
pub(super) fn relate_and_get_goals<T: Relate<I>>(
|
||||
&mut self,
|
||||
pub(super) fn eq_and_get_goals<T: Relate<I>>(
|
||||
&self,
|
||||
param_env: I::ParamEnv,
|
||||
lhs: T,
|
||||
variance: ty::Variance,
|
||||
rhs: T,
|
||||
) -> Result<Vec<Goal<I, I::Predicate>>, NoSolution> {
|
||||
let cx = self.cx();
|
||||
let delegate = self.delegate;
|
||||
let origin_span = self.origin_span;
|
||||
|
||||
let mut normalize = |alias: ty::AliasTy<I>| {
|
||||
let inference_var = self.next_ty_infer();
|
||||
|
||||
let goal = Goal::new(
|
||||
cx,
|
||||
param_env,
|
||||
ty::PredicateKind::AliasRelate(
|
||||
alias.to_ty(cx).into(),
|
||||
inference_var.into(),
|
||||
ty::AliasRelationDirection::Equate,
|
||||
),
|
||||
);
|
||||
|
||||
// Ignore the result. If we can't eagerly normalize, returning the inference variable is enough.
|
||||
let _ = self.evaluate_goal(GoalSource::TypeRelating, goal, None);
|
||||
|
||||
self.resolve_vars_if_possible(inference_var)
|
||||
};
|
||||
|
||||
Ok(delegate.relate(param_env, lhs, variance, rhs, origin_span, &mut normalize)?)
|
||||
Ok(self.delegate.relate(param_env, lhs, ty::Variance::Invariant, rhs, self.origin_span)?)
|
||||
}
|
||||
|
||||
pub(super) fn instantiate_binder_with_infer<T: TypeFoldable<I> + Copy>(
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
use std::mem;
|
||||
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_infer::traits::{Obligation, ObligationCause};
|
||||
use rustc_middle::hooks::TypeErasedInfcx;
|
||||
pub use rustc_next_trait_solver::solve::*;
|
||||
|
||||
mod delegate;
|
||||
@@ -18,13 +13,10 @@
|
||||
deeply_normalize, deeply_normalize_with_skipped_universes,
|
||||
deeply_normalize_with_skipped_universes_and_ambiguous_coroutine_goals,
|
||||
};
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::util::Providers;
|
||||
use rustc_span::Span;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
pub use select::InferCtxtSelectExt;
|
||||
|
||||
use crate::traits::ObligationCtxt;
|
||||
|
||||
fn evaluate_root_goal_for_proof_tree_raw<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
canonical_input: CanonicalInput<TyCtxt<'tcx>>,
|
||||
@@ -35,46 +27,6 @@ fn evaluate_root_goal_for_proof_tree_raw<'tcx>(
|
||||
)
|
||||
}
|
||||
|
||||
fn try_eagerly_normalize_alias<'a, 'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
type_erased_infcx: TypeErasedInfcx<'a, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
span: Span,
|
||||
alias: ty::AliasTy<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let infcx = unsafe {
|
||||
mem::transmute::<TypeErasedInfcx<'a, 'tcx>, &'a InferCtxt<'tcx>>(type_erased_infcx)
|
||||
};
|
||||
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
|
||||
let infer_term = infcx.next_ty_var(span);
|
||||
|
||||
// Dummy because we ignore the error anyway.
|
||||
// We do provide a span, because this span is used when registering opaque types.
|
||||
// For example, if we don't provide a span here, some diagnostics talking about TAIT will refer to a dummy span.
|
||||
let cause = ObligationCause::dummy_with_span(span);
|
||||
let obligation = Obligation::new(
|
||||
tcx,
|
||||
cause,
|
||||
param_env,
|
||||
ty::PredicateKind::AliasRelate(
|
||||
alias.to_ty(tcx).into(),
|
||||
infer_term.into(),
|
||||
ty::AliasRelationDirection::Equate,
|
||||
),
|
||||
);
|
||||
|
||||
ocx.register_obligation(obligation);
|
||||
|
||||
// We only use this to constrain inference variables.
|
||||
// We don't care if it errors.
|
||||
let _ = ocx.try_evaluate_obligations();
|
||||
|
||||
infcx.resolve_vars_if_possible(infer_term)
|
||||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
providers.hooks.try_eagerly_normalize_alias = try_eagerly_normalize_alias;
|
||||
providers.queries.evaluate_root_goal_for_proof_tree_raw = evaluate_root_goal_for_proof_tree_raw;
|
||||
*providers = Providers { evaluate_root_goal_for_proof_tree_raw, ..*providers };
|
||||
}
|
||||
|
||||
@@ -40,8 +40,6 @@ fn register_predicates(
|
||||
|
||||
/// Register `AliasRelate` obligation(s) that both types must be related to each other.
|
||||
fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty);
|
||||
|
||||
fn try_eagerly_normalize_alias(&mut self, alias: ty::AliasTy<I>) -> I::Ty;
|
||||
}
|
||||
|
||||
pub fn super_combine_tys<Infcx, I, R>(
|
||||
|
||||
@@ -15,7 +15,6 @@ fn relate<T: Relate<Self::Interner>>(
|
||||
variance: ty::Variance,
|
||||
rhs: T,
|
||||
span: <Self::Interner as Interner>::Span,
|
||||
normalize: &mut dyn FnMut(ty::AliasTy<Self::Interner>) -> <Self::Interner as Interner>::Ty,
|
||||
) -> Result<
|
||||
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
|
||||
TypeError<Self::Interner>,
|
||||
@@ -33,46 +32,40 @@ fn eq_structurally_relating_aliases<T: Relate<Self::Interner>>(
|
||||
>;
|
||||
}
|
||||
|
||||
impl<I: Interner, Infcx: InferCtxtLike<Interner = I>> RelateExt for Infcx {
|
||||
fn relate<T: Relate<I>>(
|
||||
impl<Infcx: InferCtxtLike> RelateExt for Infcx {
|
||||
fn relate<T: Relate<Self::Interner>>(
|
||||
&self,
|
||||
param_env: I::ParamEnv,
|
||||
param_env: <Self::Interner as Interner>::ParamEnv,
|
||||
lhs: T,
|
||||
variance: ty::Variance,
|
||||
rhs: T,
|
||||
span: I::Span,
|
||||
normalize: &mut dyn FnMut(ty::AliasTy<I>) -> I::Ty,
|
||||
) -> Result<Vec<Goal<I, I::Predicate>>, TypeError<I>> {
|
||||
let mut relate = SolverRelating::new(
|
||||
self,
|
||||
StructurallyRelateAliases::No,
|
||||
variance,
|
||||
param_env,
|
||||
span,
|
||||
normalize,
|
||||
);
|
||||
span: <Self::Interner as Interner>::Span,
|
||||
) -> Result<
|
||||
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
|
||||
TypeError<Self::Interner>,
|
||||
> {
|
||||
let mut relate =
|
||||
SolverRelating::new(self, StructurallyRelateAliases::No, variance, param_env, span);
|
||||
relate.relate(lhs, rhs)?;
|
||||
Ok(relate.goals)
|
||||
}
|
||||
|
||||
fn eq_structurally_relating_aliases<T: Relate<I>>(
|
||||
fn eq_structurally_relating_aliases<T: Relate<Self::Interner>>(
|
||||
&self,
|
||||
param_env: I::ParamEnv,
|
||||
param_env: <Self::Interner as Interner>::ParamEnv,
|
||||
lhs: T,
|
||||
rhs: T,
|
||||
span: I::Span,
|
||||
) -> Result<Vec<Goal<I, I::Predicate>>, TypeError<I>> {
|
||||
// Structurally relating, we treat aliases as rigid,
|
||||
// so we shouldn't ever try to normalize them.
|
||||
let mut normalize_unreachable = |_alias| unreachable!();
|
||||
|
||||
span: <Self::Interner as Interner>::Span,
|
||||
) -> Result<
|
||||
Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>,
|
||||
TypeError<Self::Interner>,
|
||||
> {
|
||||
let mut relate = SolverRelating::new(
|
||||
self,
|
||||
StructurallyRelateAliases::Yes,
|
||||
ty::Invariant,
|
||||
param_env,
|
||||
span,
|
||||
&mut normalize_unreachable,
|
||||
);
|
||||
relate.relate(lhs, rhs)?;
|
||||
Ok(relate.goals)
|
||||
@@ -82,14 +75,12 @@ fn eq_structurally_relating_aliases<T: Relate<I>>(
|
||||
/// Enforce that `a` is equal to or a subtype of `b`.
|
||||
pub struct SolverRelating<'infcx, Infcx, I: Interner> {
|
||||
infcx: &'infcx Infcx,
|
||||
|
||||
// Immutable fields.
|
||||
structurally_relate_aliases: StructurallyRelateAliases,
|
||||
param_env: I::ParamEnv,
|
||||
span: I::Span,
|
||||
// Mutable fields.
|
||||
ambient_variance: ty::Variance,
|
||||
normalize: &'infcx mut dyn FnMut(ty::AliasTy<I>) -> I::Ty,
|
||||
goals: Vec<Goal<I, I::Predicate>>,
|
||||
/// The cache only tracks the `ambient_variance` as it's the
|
||||
/// only field which is mutable and which meaningfully changes
|
||||
@@ -127,14 +118,12 @@ pub fn new(
|
||||
ambient_variance: ty::Variance,
|
||||
param_env: I::ParamEnv,
|
||||
span: I::Span,
|
||||
normalize: &'infcx mut dyn FnMut(ty::AliasTy<I>) -> I::Ty,
|
||||
) -> Self {
|
||||
SolverRelating {
|
||||
infcx,
|
||||
structurally_relate_aliases,
|
||||
span,
|
||||
ambient_variance,
|
||||
normalize,
|
||||
param_env,
|
||||
goals: vec![],
|
||||
cache: Default::default(),
|
||||
@@ -417,8 +406,4 @@ fn register_alias_relate_predicate(&mut self, a: I::Ty, b: I::Ty) {
|
||||
}
|
||||
})]);
|
||||
}
|
||||
|
||||
fn try_eagerly_normalize_alias(&mut self, alias: ty::AliasTy<I>) -> I::Ty {
|
||||
(self.normalize)(alias)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
|
||||
--> $DIR/unsized_coercion.rs:14:17
|
||||
|
|
||||
LL | let x = hello();
|
||||
| ^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `dyn Trait`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
//@ revisions: next old
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ check-pass
|
||||
//@[old] check-pass
|
||||
|
||||
trait Trait {}
|
||||
|
||||
@@ -12,6 +12,7 @@ impl Trait for u32 {}
|
||||
fn hello() -> Box<impl Trait> {
|
||||
if true {
|
||||
let x = hello();
|
||||
//[next]~^ ERROR: the size for values of type `dyn Trait` cannot be known at compilation time
|
||||
let y: Box<dyn Trait> = x;
|
||||
}
|
||||
Box::new(1u32)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
error[E0277]: the trait bound `dyn Send: Trait` is not satisfied
|
||||
--> $DIR/unsized_coercion3.rs:14:17
|
||||
--> $DIR/unsized_coercion3.rs:13:17
|
||||
|
|
||||
LL | let x = hello();
|
||||
| ^^^^^^^ the trait `Trait` is not implemented for `dyn Send`
|
||||
@@ -9,37 +9,7 @@ help: the trait `Trait` is implemented for `u32`
|
||||
|
|
||||
LL | impl Trait for u32 {}
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
note: required by a bound in `Box`
|
||||
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/unsized_coercion3.rs:19:5
|
||||
|
|
||||
LL | fn hello() -> Box<impl Trait + ?Sized> {
|
||||
| ------------------------
|
||||
| | |
|
||||
| | the expected opaque type
|
||||
| expected `Box<impl Trait + ?Sized>` because of return type
|
||||
...
|
||||
LL | Box::new(1u32)
|
||||
| ^^^^^^^^^^^^^^ types differ
|
||||
|
|
||||
= note: expected struct `Box<impl Trait + ?Sized>`
|
||||
found struct `Box<u32>`
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
error[E0277]: the trait bound `dyn Send: Trait` is not satisfied
|
||||
--> $DIR/unsized_coercion3.rs:11:1
|
||||
|
|
||||
LL | fn hello() -> Box<impl Trait + ?Sized> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Send`
|
||||
|
|
||||
help: the trait `Trait` is implemented for `u32`
|
||||
--> $DIR/unsized_coercion3.rs:9:1
|
||||
|
|
||||
LL | impl Trait for u32 {}
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
|
||||
--> $DIR/unsized_coercion3.rs:16:32
|
||||
--> $DIR/unsized_coercion3.rs:15:32
|
||||
|
|
||||
LL | let y: Box<dyn Send> = x;
|
||||
| ^ doesn't have a size known at compile-time
|
||||
|
||||
@@ -9,7 +9,6 @@ trait Trait {}
|
||||
impl Trait for u32 {}
|
||||
|
||||
fn hello() -> Box<impl Trait + ?Sized> {
|
||||
//[next]~^ ERROR: the trait bound `dyn Send: Trait` is not satisfied
|
||||
if true {
|
||||
let x = hello();
|
||||
//[next]~^ ERROR: the trait bound `dyn Send: Trait` is not satisfied
|
||||
@@ -17,7 +16,6 @@ fn hello() -> Box<impl Trait + ?Sized> {
|
||||
//[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
|
||||
}
|
||||
Box::new(1u32)
|
||||
//[next]~^ ERROR: mismatched types
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -9,7 +9,7 @@ note: candidate #1 is defined in the trait `Trait1`
|
||||
|
|
||||
LL | fn method(&self) {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
note: candidate #2 is defined in an impl of the trait `Trait2` for the type `T`
|
||||
note: candidate #2 is defined in the trait `Trait2`
|
||||
--> $DIR/rigid-alias-bound-is-not-inherent.rs:27:5
|
||||
|
|
||||
LL | fn method(&self) {
|
||||
|
||||
@@ -8,5 +8,6 @@ fn main() {
|
||||
//[next]~^^ ERROR expected a `FnMut(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item)` closure, found
|
||||
let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
|
||||
//[current]~^ ERROR type mismatch in closure arguments
|
||||
//[next]~^^ ERROR expected a `FnMut(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item)` closure, found
|
||||
//[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}`
|
||||
//[next]~| ERROR expected a `FnMut(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item)` closure, found
|
||||
}
|
||||
|
||||
@@ -12,6 +12,12 @@ LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0);
|
||||
note: required by a bound in `find`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error[E0271]: expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}`
|
||||
--> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:24
|
||||
|
|
||||
LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
|
||||
| ^^^^ expected `&&i32`, found integer
|
||||
|
||||
error[E0277]: expected a `FnMut(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
|
||||
--> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:29
|
||||
|
|
||||
@@ -26,6 +32,7 @@ LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
|
||||
note: required by a bound in `find`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
Some errors have detailed explanations: E0271, E0277.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
||||
|
||||
@@ -8,5 +8,6 @@ fn main() {
|
||||
//[next]~^^ ERROR expected a `FnMut(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item)` closure, found
|
||||
let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
|
||||
//[current]~^ ERROR type mismatch in closure arguments
|
||||
//[next]~^^ ERROR expected a `FnMut(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item)` closure, found
|
||||
//[next]~^^ ERROR expected `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}`
|
||||
//[next]~| ERROR expected a `FnMut(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item)` closure, found
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// revisions: next old
|
||||
//[next] compile-flags: -Znext-solver
|
||||
//@ check-pass
|
||||
// Regression test for https://github.com/rust-lang/rust/issues/154173.
|
||||
// The ICE there was caused by a (flawed) attempt to eagerly normalize during generalization.
|
||||
// The normalize would constrain other inference variables, which we couldn't deal with.
|
||||
|
||||
trait Trait<T> {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
impl Trait<u32> for () {
|
||||
type Assoc = u32;
|
||||
}
|
||||
|
||||
trait Eq {}
|
||||
impl<C: Trait<T>, T> Eq for (C, T, <C as Trait<T>>::Assoc) {}
|
||||
fn foo<A>()
|
||||
where
|
||||
((), A, A): Eq
|
||||
{}
|
||||
|
||||
fn main() {
|
||||
foo::<_>();
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
//@ revisions: old next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@ check-pass
|
||||
// Regression test for trait-system-refactor-initiative#262
|
||||
|
||||
trait View {}
|
||||
trait HasAssoc {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
struct StableVec<T>(T);
|
||||
impl<T> View for StableVec<T> {}
|
||||
|
||||
fn assert_view<F: View>(f: F) -> F { f }
|
||||
|
||||
|
||||
fn store<T>(x: StableVec<T::Assoc>)
|
||||
where
|
||||
T: HasAssoc,
|
||||
StableVec<T>: View,
|
||||
{
|
||||
let _: StableVec<T::Assoc> = assert_view(x);
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
Reference in New Issue
Block a user