Rollup merge of #135816 - BoxyUwU:root_normalizes_to_goal_ice, r=lcnr
Use `structurally_normalize` instead of manual `normalizes-to` goals in alias relate errors r? `@lcnr` I added `structurally_normalize_term` so that code that is generic over ty or const can use the structurally normalize helpers. See `tests/ui/traits/next-solver/diagnostics/alias_relate_error_uses_structurally_normalize.rs` for a description of the reason for the (now fixed) ICEs
This commit is contained in:
commit
ef0e6863c6
27 changed files with 267 additions and 121 deletions
|
@ -185,7 +185,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
CustomTypeOp::new(
|
||||
|ocx| {
|
||||
let structurally_normalize = |ty| {
|
||||
ocx.structurally_normalize(
|
||||
ocx.structurally_normalize_ty(
|
||||
&ObligationCause::misc(
|
||||
location.to_locations().span(body),
|
||||
body.source.def_id().expect_local(),
|
||||
|
@ -230,7 +230,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
ConstraintCategory::Boring,
|
||||
CustomTypeOp::new(
|
||||
|ocx| {
|
||||
ocx.structurally_normalize(
|
||||
ocx.structurally_normalize_ty(
|
||||
&ObligationCause::misc(
|
||||
location.to_locations().span(body),
|
||||
body.source.def_id().expect_local(),
|
||||
|
|
|
@ -86,7 +86,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
|
|||
if self.infcx.next_trait_solver()
|
||||
&& let ty::Alias(..) = ty.kind()
|
||||
{
|
||||
let (normalized_ty, obligations) = self.structurally_normalize(ty)?;
|
||||
let (normalized_ty, obligations) = self.structurally_normalize_ty(ty)?;
|
||||
self.state.obligations.extend(obligations);
|
||||
(AutoderefKind::Builtin, normalized_ty)
|
||||
} else {
|
||||
|
@ -166,7 +166,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
|||
}
|
||||
|
||||
let (normalized_ty, obligations) =
|
||||
self.structurally_normalize(Ty::new_projection(tcx, trait_target_def_id, [ty]))?;
|
||||
self.structurally_normalize_ty(Ty::new_projection(tcx, trait_target_def_id, [ty]))?;
|
||||
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
|
||||
self.state.obligations.extend(obligations);
|
||||
|
||||
|
@ -174,12 +174,12 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
|||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self), ret)]
|
||||
pub fn structurally_normalize(
|
||||
pub fn structurally_normalize_ty(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Option<(Ty<'tcx>, PredicateObligations<'tcx>)> {
|
||||
let ocx = ObligationCtxt::new(self.infcx);
|
||||
let Ok(normalized_ty) = ocx.structurally_normalize(
|
||||
let Ok(normalized_ty) = ocx.structurally_normalize_ty(
|
||||
&traits::ObligationCause::misc(self.span, self.body_id),
|
||||
self.param_env,
|
||||
ty,
|
||||
|
|
|
@ -320,7 +320,7 @@ fn orphan_check<'tcx>(
|
|||
}
|
||||
|
||||
let ty = if infcx.next_trait_solver() {
|
||||
ocx.structurally_normalize(
|
||||
ocx.structurally_normalize_ty(
|
||||
&cause,
|
||||
ty::ParamEnv::empty(),
|
||||
infcx.resolve_vars_if_possible(ty),
|
||||
|
|
|
@ -1124,7 +1124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
if self.next_trait_solver()
|
||||
&& let ty::Alias(..) = ty.kind()
|
||||
{
|
||||
ocx.structurally_normalize(&cause, self.param_env, ty)
|
||||
ocx.structurally_normalize_ty(&cause, self.param_env, ty)
|
||||
} else {
|
||||
Ok(ty)
|
||||
}
|
||||
|
|
|
@ -1433,7 +1433,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
// in a reentrant borrow, causing an ICE.
|
||||
let result = self
|
||||
.at(&self.misc(sp), self.param_env)
|
||||
.structurally_normalize(ty, &mut **self.fulfillment_cx.borrow_mut());
|
||||
.structurally_normalize_ty(ty, &mut **self.fulfillment_cx.borrow_mut());
|
||||
match result {
|
||||
Ok(normalized_ty) => normalized_ty,
|
||||
Err(errors) => {
|
||||
|
|
|
@ -277,23 +277,7 @@ where
|
|||
param_env: I::ParamEnv,
|
||||
ty: I::Ty,
|
||||
) -> Result<I::Ty, NoSolution> {
|
||||
if let ty::Alias(..) = ty.kind() {
|
||||
let normalized_ty = self.next_ty_infer();
|
||||
let alias_relate_goal = Goal::new(
|
||||
self.cx(),
|
||||
param_env,
|
||||
ty::PredicateKind::AliasRelate(
|
||||
ty.into(),
|
||||
normalized_ty.into(),
|
||||
ty::AliasRelationDirection::Equate,
|
||||
),
|
||||
);
|
||||
self.add_goal(GoalSource::Misc, alias_relate_goal);
|
||||
self.try_evaluate_added_goals()?;
|
||||
Ok(self.resolve_vars_if_possible(normalized_ty))
|
||||
} else {
|
||||
Ok(ty)
|
||||
}
|
||||
self.structurally_normalize_term(param_env, ty.into()).map(|term| term.expect_ty())
|
||||
}
|
||||
|
||||
/// Normalize a const for when it is structurally matched on, or more likely
|
||||
|
@ -308,22 +292,34 @@ where
|
|||
param_env: I::ParamEnv,
|
||||
ct: I::Const,
|
||||
) -> Result<I::Const, NoSolution> {
|
||||
if let ty::ConstKind::Unevaluated(..) = ct.kind() {
|
||||
let normalized_ct = self.next_const_infer();
|
||||
self.structurally_normalize_term(param_env, ct.into()).map(|term| term.expect_const())
|
||||
}
|
||||
|
||||
/// Normalize a term for when it is structurally matched on.
|
||||
///
|
||||
/// This function is necessary in nearly all cases before matching on a ty/const.
|
||||
/// Not doing so is likely to be incomplete and therefore unsound during coherence.
|
||||
fn structurally_normalize_term(
|
||||
&mut self,
|
||||
param_env: I::ParamEnv,
|
||||
term: I::Term,
|
||||
) -> Result<I::Term, NoSolution> {
|
||||
if let Some(_) = term.to_alias_term() {
|
||||
let normalized_term = self.next_term_infer_of_kind(term);
|
||||
let alias_relate_goal = Goal::new(
|
||||
self.cx(),
|
||||
param_env,
|
||||
ty::PredicateKind::AliasRelate(
|
||||
ct.into(),
|
||||
normalized_ct.into(),
|
||||
term,
|
||||
normalized_term,
|
||||
ty::AliasRelationDirection::Equate,
|
||||
),
|
||||
);
|
||||
self.add_goal(GoalSource::Misc, alias_relate_goal);
|
||||
self.try_evaluate_added_goals()?;
|
||||
Ok(self.resolve_vars_if_possible(normalized_ct))
|
||||
Ok(self.resolve_vars_if_possible(normalized_term))
|
||||
} else {
|
||||
Ok(ct)
|
||||
Ok(term)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1338,20 +1338,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||
let derive_better_type_error =
|
||||
|alias_term: ty::AliasTerm<'tcx>, expected_term: ty::Term<'tcx>| {
|
||||
let ocx = ObligationCtxt::new(self);
|
||||
let normalized_term = match expected_term.unpack() {
|
||||
ty::TermKind::Ty(_) => self.next_ty_var(DUMMY_SP).into(),
|
||||
ty::TermKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
|
||||
};
|
||||
ocx.register_obligation(Obligation::new(
|
||||
self.tcx,
|
||||
ObligationCause::dummy(),
|
||||
|
||||
let Ok(normalized_term) = ocx.structurally_normalize_term(
|
||||
&ObligationCause::dummy(),
|
||||
obligation.param_env,
|
||||
ty::PredicateKind::NormalizesTo(ty::NormalizesTo {
|
||||
alias: alias_term,
|
||||
term: normalized_term,
|
||||
}),
|
||||
));
|
||||
let _ = ocx.select_where_possible();
|
||||
alias_term.to_term(self.tcx),
|
||||
) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
if let Err(terr) = ocx.eq(
|
||||
&ObligationCause::dummy(),
|
||||
obligation.param_env,
|
||||
|
|
|
@ -709,7 +709,7 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> {
|
|||
if matches!(ty.kind(), ty::Alias(..)) {
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
ty = ocx
|
||||
.structurally_normalize(&ObligationCause::dummy(), param_env, ty)
|
||||
.structurally_normalize_ty(&ObligationCause::dummy(), param_env, ty)
|
||||
.map_err(|_| ())?;
|
||||
if !ocx.select_where_possible().is_empty() {
|
||||
return Err(());
|
||||
|
|
|
@ -319,7 +319,7 @@ where
|
|||
self.infcx.at(cause, param_env).deeply_normalize(value, &mut **self.engine.borrow_mut())
|
||||
}
|
||||
|
||||
pub fn structurally_normalize(
|
||||
pub fn structurally_normalize_ty(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
@ -327,7 +327,7 @@ where
|
|||
) -> Result<Ty<'tcx>, Vec<E>> {
|
||||
self.infcx
|
||||
.at(cause, param_env)
|
||||
.structurally_normalize(value, &mut **self.engine.borrow_mut())
|
||||
.structurally_normalize_ty(value, &mut **self.engine.borrow_mut())
|
||||
}
|
||||
|
||||
pub fn structurally_normalize_const(
|
||||
|
@ -340,4 +340,15 @@ where
|
|||
.at(cause, param_env)
|
||||
.structurally_normalize_const(value, &mut **self.engine.borrow_mut())
|
||||
}
|
||||
|
||||
pub fn structurally_normalize_term(
|
||||
&self,
|
||||
cause: &ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
value: ty::Term<'tcx>,
|
||||
) -> Result<ty::Term<'tcx>, Vec<E>> {
|
||||
self.infcx
|
||||
.at(cause, param_env)
|
||||
.structurally_normalize_term(value, &mut **self.engine.borrow_mut())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,44 +7,12 @@ use crate::traits::{NormalizeExt, Obligation};
|
|||
|
||||
#[extension(pub trait StructurallyNormalizeExt<'tcx>)]
|
||||
impl<'tcx> At<'_, 'tcx> {
|
||||
fn structurally_normalize<E: 'tcx>(
|
||||
fn structurally_normalize_ty<E: 'tcx>(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
|
||||
) -> Result<Ty<'tcx>, Vec<E>> {
|
||||
assert!(!ty.is_ty_var(), "should have resolved vars before calling");
|
||||
|
||||
if self.infcx.next_trait_solver() {
|
||||
let ty::Alias(..) = *ty.kind() else {
|
||||
return Ok(ty);
|
||||
};
|
||||
|
||||
let new_infer_ty = self.infcx.next_ty_var(self.cause.span);
|
||||
|
||||
// We simply emit an `alias-eq` goal here, since that will take care of
|
||||
// normalizing the LHS of the projection until it is a rigid projection
|
||||
// (or a not-yet-defined opaque in scope).
|
||||
let obligation = Obligation::new(
|
||||
self.infcx.tcx,
|
||||
self.cause.clone(),
|
||||
self.param_env,
|
||||
ty::PredicateKind::AliasRelate(
|
||||
ty.into(),
|
||||
new_infer_ty.into(),
|
||||
ty::AliasRelationDirection::Equate,
|
||||
),
|
||||
);
|
||||
|
||||
fulfill_cx.register_predicate_obligation(self.infcx, obligation);
|
||||
let errors = fulfill_cx.select_where_possible(self.infcx);
|
||||
if !errors.is_empty() {
|
||||
return Err(errors);
|
||||
}
|
||||
|
||||
Ok(self.infcx.resolve_vars_if_possible(new_infer_ty))
|
||||
} else {
|
||||
Ok(self.normalize(ty).into_value_registering_obligations(self.infcx, fulfill_cx))
|
||||
}
|
||||
self.structurally_normalize_term(ty.into(), fulfill_cx).map(|term| term.expect_type())
|
||||
}
|
||||
|
||||
fn structurally_normalize_const<E: 'tcx>(
|
||||
|
@ -52,14 +20,29 @@ impl<'tcx> At<'_, 'tcx> {
|
|||
ct: ty::Const<'tcx>,
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
|
||||
) -> Result<ty::Const<'tcx>, Vec<E>> {
|
||||
assert!(!ct.is_ct_infer(), "should have resolved vars before calling");
|
||||
if self.infcx.tcx.features().generic_const_exprs() {
|
||||
return Ok(super::evaluate_const(&self.infcx, ct, self.param_env));
|
||||
}
|
||||
|
||||
self.structurally_normalize_term(ct.into(), fulfill_cx).map(|term| term.expect_const())
|
||||
}
|
||||
|
||||
fn structurally_normalize_term<E: 'tcx>(
|
||||
&self,
|
||||
term: ty::Term<'tcx>,
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
|
||||
) -> Result<ty::Term<'tcx>, Vec<E>> {
|
||||
assert!(!term.is_infer(), "should have resolved vars before calling");
|
||||
|
||||
if self.infcx.next_trait_solver() {
|
||||
let ty::ConstKind::Unevaluated(..) = ct.kind() else {
|
||||
return Ok(ct);
|
||||
};
|
||||
if let None = term.to_alias_term() {
|
||||
return Ok(term);
|
||||
}
|
||||
|
||||
let new_infer_ct = self.infcx.next_const_var(self.cause.span);
|
||||
let new_infer = match term.unpack() {
|
||||
ty::TermKind::Ty(_) => self.infcx.next_ty_var(self.cause.span).into(),
|
||||
ty::TermKind::Const(_) => self.infcx.next_const_var(self.cause.span).into(),
|
||||
};
|
||||
|
||||
// We simply emit an `alias-eq` goal here, since that will take care of
|
||||
// normalizing the LHS of the projection until it is a rigid projection
|
||||
|
@ -68,11 +51,7 @@ impl<'tcx> At<'_, 'tcx> {
|
|||
self.infcx.tcx,
|
||||
self.cause.clone(),
|
||||
self.param_env,
|
||||
ty::PredicateKind::AliasRelate(
|
||||
ct.into(),
|
||||
new_infer_ct.into(),
|
||||
ty::AliasRelationDirection::Equate,
|
||||
),
|
||||
ty::PredicateKind::AliasRelate(term, new_infer, ty::AliasRelationDirection::Equate),
|
||||
);
|
||||
|
||||
fulfill_cx.register_predicate_obligation(self.infcx, obligation);
|
||||
|
@ -81,11 +60,9 @@ impl<'tcx> At<'_, 'tcx> {
|
|||
return Err(errors);
|
||||
}
|
||||
|
||||
Ok(self.infcx.resolve_vars_if_possible(new_infer_ct))
|
||||
} else if self.infcx.tcx.features().generic_const_exprs() {
|
||||
Ok(super::evaluate_const(&self.infcx, ct, self.param_env))
|
||||
Ok(self.infcx.resolve_vars_if_possible(new_infer))
|
||||
} else {
|
||||
Ok(self.normalize(ct).into_value_registering_obligations(self.infcx, fulfill_cx))
|
||||
Ok(self.normalize(term).into_value_registering_obligations(self.infcx, fulfill_cx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ use ignore::Walk;
|
|||
const ENTRY_LIMIT: u32 = 901;
|
||||
// FIXME: The following limits should be reduced eventually.
|
||||
|
||||
const ISSUES_ENTRY_LIMIT: u32 = 1663;
|
||||
const ISSUES_ENTRY_LIMIT: u32 = 1664;
|
||||
|
||||
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
|
||||
"rs", // test source files
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0271]: expected `{async closure@is-not-fn.rs:5:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:5:23: 5:25}`
|
||||
--> $DIR/is-not-fn.rs:5:14
|
||||
error[E0271]: expected `{async closure@is-not-fn.rs:8:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}`
|
||||
--> $DIR/is-not-fn.rs:8:14
|
||||
|
|
||||
LL | needs_fn(async || {});
|
||||
| -------- ^^^^^^^^^^^ expected `()`, found `async` closure body
|
||||
|
@ -7,9 +7,9 @@ LL | needs_fn(async || {});
|
|||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found `async` closure body `{async closure body@$DIR/is-not-fn.rs:5:23: 5:25}`
|
||||
found `async` closure body `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}`
|
||||
note: required by a bound in `needs_fn`
|
||||
--> $DIR/is-not-fn.rs:4:25
|
||||
--> $DIR/is-not-fn.rs:7:25
|
||||
|
|
||||
LL | fn needs_fn(x: impl FnOnce()) {}
|
||||
| ^^^^^^^^ required by this bound in `needs_fn`
|
19
tests/ui/async-await/async-closures/is-not-fn.next.stderr
Normal file
19
tests/ui/async-await/async-closures/is-not-fn.next.stderr
Normal file
|
@ -0,0 +1,19 @@
|
|||
error[E0271]: expected `{async closure@is-not-fn.rs:8:14}` to be a closure that returns `()`, but it returns `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}`
|
||||
--> $DIR/is-not-fn.rs:8:14
|
||||
|
|
||||
LL | needs_fn(async || {});
|
||||
| -------- ^^^^^^^^^^^ expected `()`, found `async` closure body
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found `async` closure body `{async closure body@$DIR/is-not-fn.rs:8:23: 8:25}`
|
||||
note: required by a bound in `needs_fn`
|
||||
--> $DIR/is-not-fn.rs:7:25
|
||||
|
|
||||
LL | fn needs_fn(x: impl FnOnce()) {}
|
||||
| ^^^^^^^^ required by this bound in `needs_fn`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
|
@ -1,7 +1,10 @@
|
|||
//@ edition:2021
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
fn main() {
|
||||
fn needs_fn(x: impl FnOnce()) {}
|
||||
needs_fn(async || {});
|
||||
//~^ ERROR expected `{async closure@is-not-fn.rs:5:14}` to be a closure that returns `()`
|
||||
//~^ ERROR expected `{async closure@is-not-fn.rs:8:14}` to be a closure that returns `()`
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
error[E0407]: method `line_stream` is not a member of trait `X`
|
||||
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:5
|
||||
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:5
|
||||
|
|
||||
LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X`
|
||||
|
||||
error[E0049]: type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter
|
||||
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:22:21
|
||||
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:21
|
||||
|
|
||||
LL | type LineStream<'a, Repr>
|
||||
| -- ----
|
||||
|
@ -18,7 +18,7 @@ LL | type LineStream<'c, 'd> = impl Stream;
|
|||
| found 0 type parameters
|
||||
|
||||
error[E0277]: `()` is not a future
|
||||
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:43
|
||||
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:43
|
||||
|
|
||||
LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
|
|
@ -0,0 +1,29 @@
|
|||
error[E0407]: method `line_stream` is not a member of trait `X`
|
||||
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:5
|
||||
|
|
||||
LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X`
|
||||
|
||||
error[E0049]: type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter
|
||||
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:21
|
||||
|
|
||||
LL | type LineStream<'a, Repr>
|
||||
| -- ----
|
||||
| |
|
||||
| expected 1 type parameter
|
||||
...
|
||||
LL | type LineStream<'c, 'd> = impl Stream;
|
||||
| ^^ ^^
|
||||
| |
|
||||
| found 0 type parameters
|
||||
|
||||
error[E0271]: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> == ()`
|
||||
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:43
|
||||
|
|
||||
LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0049, E0271, E0407.
|
||||
For more information about an error, try `rustc --explain E0049`.
|
|
@ -1,3 +1,6 @@
|
|||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
// test for ICE #112823
|
||||
// Unexpected parameter Type(Repr) when substituting in region
|
||||
|
||||
|
@ -23,8 +26,9 @@ impl X for Y {
|
|||
//~^ ERROR type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter
|
||||
type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>>;
|
||||
fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
|
||||
//~^ ERROR `()` is not a future
|
||||
//~^^ method `line_stream` is not a member of trait `X`
|
||||
//[current]~^ ERROR `()` is not a future
|
||||
//[next]~^^ ERROR type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> == ()`
|
||||
//~^^^ method `line_stream` is not a member of trait `X`
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
--> $DIR/issue-33941.rs:6:36
|
||||
--> $DIR/issue-33941.rs:9:36
|
||||
|
|
||||
LL | for _ in HashMap::new().iter().cloned() {}
|
||||
| ^^^^^^ expected `&_`, found `(&_, &_)`
|
||||
|
@ -7,7 +7,7 @@ LL | for _ in HashMap::new().iter().cloned() {}
|
|||
= note: expected reference `&_`
|
||||
found tuple `(&_, &_)`
|
||||
note: the method call chain might not have had the expected associated types
|
||||
--> $DIR/issue-33941.rs:6:29
|
||||
--> $DIR/issue-33941.rs:9:29
|
||||
|
|
||||
LL | for _ in HashMap::new().iter().cloned() {}
|
||||
| -------------- ^^^^^^ `Iterator::Item` is `(&_, &_)` here
|
||||
|
@ -17,7 +17,7 @@ note: required by a bound in `cloned`
|
|||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
--> $DIR/issue-33941.rs:6:14
|
||||
--> $DIR/issue-33941.rs:9:14
|
||||
|
|
||||
LL | for _ in HashMap::new().iter().cloned() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&_`, found `(&_, &_)`
|
25
tests/ui/issues/issue-33941.next.stderr
Normal file
25
tests/ui/issues/issue-33941.next.stderr
Normal file
|
@ -0,0 +1,25 @@
|
|||
error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
--> $DIR/issue-33941.rs:9:36
|
||||
|
|
||||
LL | for _ in HashMap::new().iter().cloned() {}
|
||||
| ^^^^^^ expected `&_`, found `(&_, &_)`
|
||||
|
|
||||
= note: expected reference `&_`
|
||||
found tuple `(&_, &_)`
|
||||
note: required by a bound in `cloned`
|
||||
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
|
||||
|
||||
error[E0271]: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
--> $DIR/issue-33941.rs:9:14
|
||||
|
|
||||
LL | for _ in HashMap::new().iter().cloned() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&_`, found `(&_, &_)`
|
||||
|
|
||||
= note: expected reference `&_`
|
||||
found tuple `(&_, &_)`
|
||||
= note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator`
|
||||
= note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `IntoIterator`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
|
@ -1,8 +1,12 @@
|
|||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ compile-flags: -Zdeduplicate-diagnostics=yes
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn main() {
|
||||
for _ in HashMap::new().iter().cloned() {} //~ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
for _ in HashMap::new().iter().cloned() {}
|
||||
//~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
//~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@[current] run-rustfix
|
||||
fn main() {
|
||||
let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
|
||||
//[current]~^ ERROR type mismatch in closure arguments
|
||||
//[next]~^^ ERROR expected a `FnMut(&<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 `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}`
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/closure-arg-type-mismatch-issue-45727.rs:3:24
|
||||
--> $DIR/closure-arg-type-mismatch-issue-45727.rs:6:24
|
||||
|
|
||||
LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0);
|
||||
| ^^^^ -------- found signature defined here
|
||||
|
@ -16,7 +16,7 @@ LL | let _ = (-10..=10).find(|x: &i32| x.signum() == 0);
|
|||
| +
|
||||
|
||||
error[E0631]: type mismatch in closure arguments
|
||||
--> $DIR/closure-arg-type-mismatch-issue-45727.rs:4:24
|
||||
--> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:24
|
||||
|
|
||||
LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
|
||||
| ^^^^ ----------- found signature defined here
|
|
@ -1,5 +0,0 @@
|
|||
//@ run-rustfix
|
||||
fn main() {
|
||||
let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
|
||||
let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
error[E0277]: expected a `FnMut(&<RangeInclusive<{integer}> as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
|
||||
--> $DIR/closure-arg-type-mismatch-issue-45727.rs:6:29
|
||||
|
|
||||
LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0);
|
||||
| ---- ^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(&<RangeInclusive<{integer}> as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `for<'a> FnMut(&'a <RangeInclusive<{integer}> as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
|
||||
= note: expected a closure with arguments `(i32,)`
|
||||
found a closure with arguments `(&<RangeInclusive<{integer}> as Iterator>::Item,)`
|
||||
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:33
|
||||
|
|
||||
LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
|
||||
| ^^^^^^ expected `&&i32`, found integer
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0271, E0277.
|
||||
For more information about an error, try `rustc --explain E0271`.
|
|
@ -1,5 +1,12 @@
|
|||
//@ run-rustfix
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@[current] run-rustfix
|
||||
fn main() {
|
||||
let _ = (-10..=10).find(|x: i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
|
||||
let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); //~ ERROR type mismatch in closure arguments
|
||||
let _ = (-10..=10).find(|x: i32| x.signum() == 0);
|
||||
//[current]~^ ERROR type mismatch in closure arguments
|
||||
//[next]~^^ ERROR expected a `FnMut(&<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 `RangeInclusive<{integer}>` to be an iterator that yields `&&i32`, but it yields `{integer}`
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
//@ compile-flags: -Znext-solver
|
||||
|
||||
// When encountering a fulfillment error from an `alias-relate` goal failing, we
|
||||
// would previously manually construct a `normalizes-to` goal involving the alias
|
||||
// and an infer var. This would then ICE as normalization would return a nested
|
||||
// goal (the `T: Sized` from the `Trait` impl for `Foo<T>` below) from the root goal
|
||||
// which is not supported.
|
||||
|
||||
struct Foo<T>(T);
|
||||
|
||||
trait Trait {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
// `T: Sized` being explicit is not required, but the bound being present *is*.
|
||||
impl<T: Sized> Trait for Foo<T> {
|
||||
type Assoc = u64;
|
||||
}
|
||||
|
||||
fn bar<T: Trait<Assoc = u32>>(_: T) {}
|
||||
|
||||
fn main() {
|
||||
let foo = Foo(Default::default());
|
||||
bar(foo);
|
||||
//~^ ERROR: type mismatch resolving `<Foo<_> as Trait>::Assoc == u32`
|
||||
// Here diagnostics would manually construct a `<Foo<?y> as Trait>::Assoc normalizes-to ?x` goal
|
||||
// which would return a nested goal of `?y: Sized` from the impl.
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
error[E0271]: type mismatch resolving `<Foo<_> as Trait>::Assoc == u32`
|
||||
--> $DIR/alias_relate_error_uses_structurally_normalize.rs:24:9
|
||||
|
|
||||
LL | bar(foo);
|
||||
| --- ^^^ expected `u32`, found `u64`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `bar`
|
||||
--> $DIR/alias_relate_error_uses_structurally_normalize.rs:20:17
|
||||
|
|
||||
LL | fn bar<T: Trait<Assoc = u32>>(_: T) {}
|
||||
| ^^^^^^^^^^^ required by this bound in `bar`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0271`.
|
Loading…
Add table
Add a link
Reference in a new issue