Auto merge of #155767 - adwinwhite:eager-norm-outside, r=lcnr

`-Znext-solver` Eager normalization outside of solver 




This PR adds a normalization routine for the next solver that behaves the same as the normalization in the old solver.
The new routine is used to normalize eagerly outside of the next solver.

This is [part 2](https://rust-lang.zulipchat.com/#narrow/channel/364551-t-types.2Ftrait-system-refactor/topic/Eager.20normalization.2C.20ahoy.21/near/582996783) of modifying the next solver to support eager normalization.

Those test changes are mostly wording changes, duplicating some errors or reducing some duplicates. But I could have overlooked something.
Notably it fixes the first, third and fourth examples in https://github.com/rust-lang/trait-system-refactor-initiative/issues/191, but not the second variant.

It's probably easier to review commit by commit.

Fixes rust-lang/rust#151308
Fixes rust-lang/rust#101557
Fixes rust-lang/rust#119692
Fixes rust-lang/rust#136859
This commit is contained in:
bors
2026-05-02 20:56:41 +00:00
139 changed files with 1136 additions and 1479 deletions
@@ -8,9 +8,7 @@ use rustc_middle::mir::{Body, ConstraintCategory};
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, Unnormalized, Upcast};
use rustc_span::Span;
use rustc_span::def_id::DefId;
use rustc_trait_selection::solve::NoSolution;
use rustc_trait_selection::traits::ObligationCause;
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
use tracing::{debug, instrument};
@@ -242,71 +240,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
body.source.def_id().expect_local(),
);
if self.infcx.next_trait_solver() {
let param_env = self.infcx.param_env;
// FIXME: Make this into a real type op?
self.fully_perform_op(
location.to_locations(),
ConstraintCategory::Boring,
CustomTypeOp::new(
|ocx| {
let structurally_normalize = |ty| {
ocx.structurally_normalize_ty(&cause, param_env, Unnormalized::new_wip(ty))
.unwrap_or_else(|_| bug!("struct tail should have been computable, since we computed it in HIR"))
};
let tail = tcx.struct_tail_raw(
ty,
&cause,
structurally_normalize,
|| {},
);
Ok(tail)
},
"normalizing struct tail",
),
)
.unwrap_or_else(|guar| Ty::new_error(tcx, guar))
} else {
let mut normalize = |ty| self.normalize(ty, location);
let tail = tcx.struct_tail_raw(ty, &cause, &mut normalize, || {});
normalize(tail)
}
}
#[instrument(skip(self), level = "debug")]
pub(super) fn structurally_resolve(
&mut self,
ty: Ty<'tcx>,
location: impl NormalizeLocation,
) -> Ty<'tcx> {
if self.infcx.next_trait_solver() {
let body = self.body;
let param_env = self.infcx.param_env;
// FIXME: Make this into a real type op?
self.fully_perform_op(
location.to_locations(),
ConstraintCategory::Boring,
CustomTypeOp::new(
|ocx| {
ocx.structurally_normalize_ty(
&ObligationCause::misc(
location.to_locations().span(body),
body.source.def_id().expect_local(),
),
param_env,
Unnormalized::new_wip(ty),
)
.map_err(|_| NoSolution)
},
"normalizing struct tail",
),
)
.unwrap_or_else(|guar| Ty::new_error(self.tcx(), guar))
} else {
self.normalize(ty, location)
}
let mut normalize = |ty| self.normalize(ty, location);
let tail = tcx.struct_tail_raw(ty, &cause, &mut normalize, || {});
normalize(tail)
}
#[instrument(skip(self), level = "debug")]
@@ -461,7 +461,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let projected_ty = curr_projected_ty.projection_ty_core(
tcx,
proj,
|ty| self.structurally_resolve(ty, locations),
|ty| self.normalize(ty, locations),
|ty, variant_index, field, ()| PlaceTy::field_ty(tcx, ty, variant_index, field),
|_| unreachable!(),
);
+6 -26
View File
@@ -87,19 +87,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
let (kind, new_ty) =
if let Some(ty) = self.state.cur_ty.builtin_deref(self.include_raw_pointers) {
debug_assert_eq!(ty, self.infcx.resolve_vars_if_possible(ty));
// NOTE: we may still need to normalize the built-in deref in case
// we have some type like `&<Ty as Trait>::Assoc`, since users of
// autoderef expect this type to have been structurally normalized.
if self.infcx.next_trait_solver()
&& let ty::Alias(..) = ty.kind()
{
let (normalized_ty, obligations) =
self.structurally_normalize_ty(Unnormalized::new_wip(ty))?;
self.state.obligations.extend(obligations);
(AutoderefKind::Builtin, normalized_ty)
} else {
(AutoderefKind::Builtin, ty)
}
(AutoderefKind::Builtin, ty)
} else if let Some(ty) = self.overloaded_deref_ty(self.state.cur_ty) {
// The overloaded deref check already normalizes the pointee type.
(AutoderefKind::Overloaded, ty)
@@ -177,9 +165,8 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
return None;
}
let (normalized_ty, obligations) = self.structurally_normalize_ty(Unnormalized::new(
Ty::new_projection(tcx, trait_target_def_id, [ty]),
))?;
let (normalized_ty, obligations) = self
.normalize_ty(Unnormalized::new(Ty::new_projection(tcx, trait_target_def_id, [ty])))?;
debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations);
self.state.obligations.extend(obligations);
@@ -187,25 +174,18 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
}
#[instrument(level = "debug", skip(self), ret)]
pub fn structurally_normalize_ty(
pub fn normalize_ty(
&self,
ty: Unnormalized<'tcx, Ty<'tcx>>,
) -> Option<(Ty<'tcx>, PredicateObligations<'tcx>)> {
let ocx = ObligationCtxt::new(self.infcx);
let Ok(normalized_ty) = ocx.structurally_normalize_ty(
let normalized_ty = ocx.normalize(
&traits::ObligationCause::misc(self.span, self.body_id),
self.param_env,
ty,
) else {
// We shouldn't have errors here in the old solver, except for
// evaluate/fulfill mismatches, but that's not a reason for an ICE.
return None;
};
);
let errors = ocx.try_evaluate_obligations();
if !errors.is_empty() {
if self.infcx.next_trait_solver() {
unreachable!();
}
// We shouldn't have errors here in the old solver, except for
// evaluate/fulfill mismatches, but that's not a reason for an ICE.
debug!(?errors, "encountered errors while fulfilling");
@@ -315,17 +315,6 @@ fn orphan_check<'tcx>(
return Ok(user_ty);
}
let ty = if infcx.next_trait_solver() {
ocx.structurally_normalize_ty(
&cause,
ty::ParamEnv::empty(),
Unnormalized::new_wip(infcx.resolve_vars_if_possible(ty)),
)
.unwrap_or(ty)
} else {
ty
};
Ok::<_, !>(ty)
};
+1 -2
View File
@@ -60,8 +60,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// type in that case)
let mut all_arms_diverge = Diverges::WarnedAlways;
let expected =
orig_expected.try_structurally_resolve_and_adjust_for_branches(self, expr.span);
let expected = orig_expected.try_structurally_resolve_and_adjust_for_branches(self);
debug!(?expected);
let mut coercion = {
+2 -3
View File
@@ -79,7 +79,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => self.check_expr(callee_expr),
};
let expr_ty = self.try_structurally_resolve_type(call_expr.span, original_callee_ty);
let expr_ty = self.resolve_vars_with_obligations(original_callee_ty);
let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
let mut result = None;
@@ -211,8 +211,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
arg_exprs: &'tcx [hir::Expr<'tcx>],
autoderef: &Autoderef<'a, 'tcx>,
) -> Option<CallStep<'tcx>> {
let adjusted_ty =
self.try_structurally_resolve_type(autoderef.span(), autoderef.final_ty());
let adjusted_ty = self.resolve_vars_with_obligations(autoderef.final_ty());
// If the callee is a function pointer or a closure, then we're all set.
match *adjusted_ty.kind() {
+3 -3
View File
@@ -102,7 +102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return Ok(Some(PointerKind::Thin));
}
let t = self.try_structurally_resolve_type(span, t);
let t = self.resolve_vars_with_obligations(t);
Ok(match *t.kind() {
ty::Slice(_) | ty::Str => Some(PointerKind::Length),
@@ -1041,8 +1041,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
mut m_cast: ty::TypeAndMut<'tcx>,
) -> Result<CastKind, CastError<'tcx>> {
// array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
m_expr.ty = fcx.try_structurally_resolve_type(self.expr_span, m_expr.ty);
m_cast.ty = fcx.try_structurally_resolve_type(self.cast_span, m_cast.ty);
m_expr.ty = fcx.resolve_vars_with_obligations(m_expr.ty);
m_cast.ty = fcx.resolve_vars_with_obligations(m_cast.ty);
if m_expr.mutbl >= m_cast.mutbl
&& let ty::Array(ety, _) = m_expr.ty.kind()
+4 -5
View File
@@ -59,10 +59,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// closure sooner rather than later, so first examine the expected
// type, and see if can glean a closure kind from there.
let (expected_sig, expected_kind) = match expected.to_option(self) {
Some(ty) => self.deduce_closure_signature(
self.try_structurally_resolve_type(expr_span, ty),
closure.kind,
),
Some(ty) => {
self.deduce_closure_signature(self.resolve_vars_with_obligations(ty), closure.kind)
}
None => (None, None),
};
@@ -963,7 +962,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let closure_span = self.tcx.def_span(body_def_id);
let ret_ty = ret_coercion.borrow().expected_ty();
let ret_ty = self.try_structurally_resolve_type(closure_span, ret_ty);
let ret_ty = self.resolve_vars_with_obligations(ret_ty);
let get_future_output = |predicate: ty::Predicate<'tcx>, span| {
// Search for a pending obligation like
+4 -27
View File
@@ -1051,17 +1051,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
expr: &'tcx hir::Expr<'tcx>,
expr_ty: Ty<'tcx>,
mut target: Ty<'tcx>,
target: Ty<'tcx>,
allow_two_phase: AllowTwoPhase,
cause: Option<ObligationCause<'tcx>>,
) -> RelateResult<'tcx, Ty<'tcx>> {
let source = self.try_structurally_resolve_type(expr.span, expr_ty);
if self.next_trait_solver() {
target = self.try_structurally_resolve_type(
cause.as_ref().map_or(expr.span, |cause| cause.span),
target,
);
}
let source = self.resolve_vars_with_obligations(expr_ty);
debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
let cause =
@@ -1099,23 +1093,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Make sure to structurally resolve the types, since we use
// the `TyKind`s heavily in coercion.
let ocx = ObligationCtxt::new(self);
let structurally_resolve = |ty| {
let ty = self.shallow_resolve(ty);
if self.next_trait_solver()
&& let ty::Alias(..) = ty.kind()
{
ocx.structurally_normalize_ty(&cause, self.param_env, Unnormalized::new_wip(ty))
} else {
Ok(ty)
}
};
let Ok(expr_ty) = structurally_resolve(expr_ty) else {
return false;
};
let Ok(target_ty) = structurally_resolve(target_ty) else {
return false;
};
let Ok(ok) = coerce.coerce(expr_ty, target_ty) else {
return false;
};
@@ -1261,8 +1238,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
new: &hir::Expr<'_>,
new_ty: Ty<'tcx>,
) -> RelateResult<'tcx, Ty<'tcx>> {
let prev_ty = self.try_structurally_resolve_type(cause.span, prev_ty);
let new_ty = self.try_structurally_resolve_type(new.span, new_ty);
let prev_ty = self.resolve_vars_with_obligations(prev_ty);
let new_ty = self.resolve_vars_with_obligations(new_ty);
debug!(
"coercion::try_find_coercion_lub({:?}, {:?}, exprs={:?} exprs)",
prev_ty,
+1 -5
View File
@@ -260,11 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
mut expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
allow_two_phase: AllowTwoPhase,
) -> Result<Ty<'tcx>, Diag<'a>> {
let expected = if self.next_trait_solver() {
expected
} else {
self.resolve_vars_with_obligations(expected)
};
let expected = self.resolve_vars_with_obligations(expected);
let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
Ok(ty) => return Ok(ty),
+1 -2
View File
@@ -43,11 +43,10 @@ impl<'a, 'tcx> Expectation<'tcx> {
pub(super) fn try_structurally_resolve_and_adjust_for_branches(
&self,
fcx: &FnCtxt<'a, 'tcx>,
span: Span,
) -> Expectation<'tcx> {
match *self {
ExpectHasType(ety) => {
let ety = fcx.try_structurally_resolve_type(span, ety);
let ety = fcx.resolve_vars_with_obligations(ety);
if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation }
}
ExpectRvalueLikeUnsized(ety) => ExpectRvalueLikeUnsized(ety),
+9 -9
View File
@@ -82,7 +82,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// While we don't allow *arbitrary* coercions here, we *do* allow
// coercions from ! to `expected`.
if self.try_structurally_resolve_type(expr.span, ty).is_never()
if self.resolve_vars_with_obligations(ty).is_never()
&& self.tcx.expr_guaranteed_to_constitute_read_for_never(expr)
{
if let Some(adjustments) = self.typeck_results.borrow().adjustments().get(expr.hir_id) {
@@ -300,7 +300,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// unless it's a place expression that isn't being read from, in which case
// diverging would be unsound since we may never actually read the `!`.
// e.g. `let _ = *never_ptr;` with `never_ptr: *const !`.
if self.try_structurally_resolve_type(expr.span, ty).is_never()
if self.resolve_vars_with_obligations(ty).is_never()
&& self.tcx.expr_guaranteed_to_constitute_read_for_never(expr)
{
self.diverges.set(self.diverges.get() | Diverges::always(expr.span));
@@ -454,7 +454,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expr: &'tcx hir::Expr<'tcx>,
) -> Ty<'tcx> {
let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| {
match self.try_structurally_resolve_type(expr.span, ty).kind() {
match self.resolve_vars_with_obligations(ty).kind() {
ty::Ref(_, ty, _) | ty::RawPtr(ty, _) => {
if oprnd.is_syntactic_place_expr() {
// Places may legitimately have unsized types.
@@ -1187,7 +1187,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let cond_diverges = self.diverges.get();
self.diverges.set(Diverges::Maybe);
let expected = orig_expected.try_structurally_resolve_and_adjust_for_branches(self, sp);
let expected = orig_expected.try_structurally_resolve_and_adjust_for_branches(self);
let then_ty = self.check_expr_with_expectation(then_expr, expected);
let then_diverges = self.diverges.get();
self.diverges.set(Diverges::Maybe);
@@ -1457,7 +1457,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Expectation<'tcx>,
) -> Ty<'tcx> {
let rcvr_t = self.check_expr(rcvr);
let rcvr_t = self.try_structurally_resolve_type(rcvr.span, rcvr_t);
let rcvr_t = self.resolve_vars_with_obligations(rcvr_t);
match self.lookup_method(rcvr_t, segment, segment.ident.span, expr, rcvr, args) {
Ok(method) => {
@@ -1644,11 +1644,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let coerce_to = expected
.to_option(self)
.and_then(|uty| {
self.try_structurally_resolve_type(expr.span, uty)
self.resolve_vars_with_obligations(uty)
.builtin_index()
// Avoid using the original type variable as the coerce_to type, as it may resolve
// during the first coercion instead of being the LUB type.
.filter(|t| !self.try_structurally_resolve_type(expr.span, *t).is_ty_var())
.filter(|t| !self.resolve_vars_with_obligations(*t).is_ty_var())
})
.unwrap_or_else(|| self.next_ty_var(expr.span));
let mut coerce = CoerceMany::with_capacity(coerce_to, args.len());
@@ -1773,7 +1773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> {
let mut expectations = expected
.only_has_type(self)
.and_then(|ty| self.try_structurally_resolve_type(expr.span, ty).opt_tuple_fields())
.and_then(|ty| self.resolve_vars_with_obligations(ty).opt_tuple_fields())
.unwrap_or_default()
.iter();
@@ -1847,7 +1847,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
let tcx = self.tcx;
let adt_ty = self.try_structurally_resolve_type(path_span, adt_ty);
let adt_ty = self.resolve_vars_with_obligations(adt_ty);
let adt_ty_hint = expected.only_has_type(self).and_then(|expected| {
self.fudge_inference_if_ok(|| {
let ocx = ObligationCtxt::new(self);
+2 -37
View File
@@ -470,13 +470,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let tail = self.tcx.struct_tail_raw(
ty,
&self.misc(span),
|ty| {
if self.next_trait_solver() {
self.try_structurally_resolve_type(span, ty)
} else {
self.normalize(span, Unnormalized::new_wip(ty))
}
},
|ty| self.normalize(span, Unnormalized::new_wip(ty)),
|| {},
);
// Sized types have static alignment, and so do slices.
@@ -1432,35 +1426,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}
/// Try to resolve `ty` to a structural type, normalizing aliases.
///
/// In case there is still ambiguity, the returned type may be an inference
/// variable. This is different from `structurally_resolve_type` which errors
/// in this case.
#[instrument(level = "debug", skip(self, sp), ret)]
pub(crate) fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
if self.next_trait_solver()
&& let ty::Alias(..) = ty.kind()
{
// We need to use a separate variable here as otherwise the temporary for
// `self.fulfillment_cx.borrow_mut()` is alive in the `Err` branch, resulting
// in a reentrant borrow, causing an ICE.
let result = self.at(&self.misc(sp), self.param_env).structurally_normalize_ty(
Unnormalized::new_wip(ty),
&mut **self.fulfillment_cx.borrow_mut(),
);
match result {
Ok(normalized_ty) => normalized_ty,
Err(errors) => {
let guar = self.err_ctxt().report_fulfillment_errors(errors);
return Ty::new_error(self.tcx, guar);
}
}
} else {
self.resolve_vars_with_obligations(ty)
}
}
#[instrument(level = "debug", skip(self, sp), ret)]
pub(crate) fn try_structurally_resolve_const(
&self,
@@ -1502,7 +1467,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// If no resolution is possible, then an error is reported.
/// Numeric inference variables may be left unresolved.
pub(crate) fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
let ty = self.try_structurally_resolve_type(sp, ty);
let ty = self.resolve_vars_with_obligations(ty);
if !ty.is_ty_var() { ty } else { self.type_must_be_known_at_this_point(sp, ty) }
}
@@ -218,29 +218,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_place_expr_if_unsized(fn_input_ty, arg_expr);
}
let formal_input_tys_ns;
let formal_input_tys = if self.next_trait_solver() {
// In the new solver, the normalizations are done lazily.
// Because of this, if we encounter unnormalized alias types inside this
// fudge scope, we might lose the relationships between them and other vars
// when fudging inference variables created here.
// So, we utilize generalization to normalize aliases by adding a new
// inference var and equating it with the type we want to pull out of the
// fudge scope.
formal_input_tys_ns = formal_input_tys
.iter()
.map(|&ty| {
let generalized_ty = self.next_ty_var(call_span);
self.demand_eqtype(call_span, ty, generalized_ty);
generalized_ty
})
.collect_vec();
formal_input_tys_ns.as_slice()
} else {
formal_input_tys
};
// First, let's unify the formal method signature with the expectation eagerly.
// We use this to guide coercion inference; it's output is "fudged" which means
// any remaining type variables are assigned to new, unrelated variables. This
+2 -14
View File
@@ -411,11 +411,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. },
..
}) if !ty.has_escaping_bound_vars() => {
if self.next_trait_solver() {
self.try_structurally_resolve_type(span, ty).ty_adt_def()
} else {
self.normalize(span, Unnormalized::new_wip(ty)).ty_adt_def()
}
self.normalize(span, Unnormalized::new_wip(ty)).ty_adt_def()
}
_ => None,
}
@@ -485,15 +481,7 @@ pub(crate) struct LoweredTy<'tcx> {
impl<'tcx> LoweredTy<'tcx> {
fn from_raw(fcx: &FnCtxt<'_, 'tcx>, span: Span, raw: Ty<'tcx>) -> LoweredTy<'tcx> {
// FIXME(-Znext-solver=no): This is easier than requiring all uses of `LoweredTy`
// to call `try_structurally_resolve_type` instead. This seems like a lot of
// effort, especially as we're still supporting the old solver. We may revisit
// this in the future.
let normalized = if fcx.next_trait_solver() {
fcx.try_structurally_resolve_type(span, raw)
} else {
fcx.normalize(span, Unnormalized::new_wip(raw))
};
let normalized = fcx.normalize(span, Unnormalized::new_wip(raw));
LoweredTy { raw, normalized }
}
}
+4 -4
View File
@@ -44,7 +44,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
fn expr_ty(&self, expr: &hir::Expr<'tcx>) -> Ty<'tcx> {
let ty = self.fcx.typeck_results.borrow().expr_ty_adjusted(expr);
let ty = self.fcx.try_structurally_resolve_type(expr.span, ty);
let ty = self.fcx.resolve_vars_with_obligations(ty);
if ty.has_non_region_infer() {
Ty::new_misc_error(self.tcx())
} else {
@@ -53,13 +53,13 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
}
// FIXME(compiler-errors): This could use `<$ty as Pointee>::Metadata == ()`
fn is_thin_ptr_ty(&self, span: Span, ty: Ty<'tcx>) -> bool {
fn is_thin_ptr_ty(&self, ty: Ty<'tcx>) -> bool {
// Type still may have region variables, but `Sized` does not depend
// on those, so just erase them before querying.
if self.fcx.type_is_sized_modulo_regions(self.fcx.param_env, ty) {
return true;
}
if let ty::Foreign(..) = self.fcx.try_structurally_resolve_type(span, ty).kind() {
if let ty::Foreign(..) = self.fcx.resolve_vars_with_obligations(ty).kind() {
return true;
}
false
@@ -90,7 +90,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
ty::Float(FloatTy::F128) => Ok(InlineAsmType::F128),
ty::FnPtr(..) => Ok(asm_ty_isize),
ty::RawPtr(elem_ty, _) => {
if self.is_thin_ptr_ty(span, elem_ty) {
if self.is_thin_ptr_ty(elem_ty) {
Ok(asm_ty_isize)
} else {
Err(NonAsmTypeReason::NotSizedPtr(ty))
+5 -12
View File
@@ -2112,21 +2112,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// `WhereClauseCandidate` requires that the self type is a param,
// because it has special behavior with candidate preference as an
// inherent pick.
match ocx.structurally_normalize_ty(
let ty = ocx.normalize(
cause,
self.param_env,
Unnormalized::new_wip(trait_ref.self_ty()),
) {
Ok(ty) => {
if !matches!(ty.kind(), ty::Param(_)) {
debug!("--> not a param ty: {xform_self_ty:?}");
return ProbeResult::NoMatch;
}
}
Err(errors) => {
debug!("--> cannot relate self-types {:?}", errors);
return ProbeResult::NoMatch;
}
);
if !matches!(ty.kind(), ty::Param(_)) {
debug!("--> not a param ty: {xform_self_ty:?}");
return ProbeResult::NoMatch;
}
}
+8 -8
View File
@@ -497,7 +497,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let expected = if let AdjustMode::Peel { .. } = adjust_mode
&& pat.default_binding_modes
{
self.try_structurally_resolve_type(pat.span, expected)
self.resolve_vars_with_obligations(expected)
} else {
expected
};
@@ -816,7 +816,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut peeled_ty = lit_ty;
let mut pat_ref_layers = 0;
while let ty::Ref(_, inner_ty, mutbl) =
*self.try_structurally_resolve_type(pat.span, peeled_ty).kind()
*self.resolve_vars_with_obligations(peeled_ty).kind()
{
// We rely on references at the head of constants being immutable.
debug_assert!(mutbl.is_not());
@@ -962,7 +962,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match *expected.kind() {
// Allow `b"...": &[u8]`
ty::Ref(_, inner_ty, _)
if self.try_structurally_resolve_type(span, inner_ty).is_slice() =>
if self.resolve_vars_with_obligations(inner_ty).is_slice() =>
{
trace!(?expr.hir_id.local_id, "polymorphic byte string lit");
pat_ty = Ty::new_imm_ref(
@@ -991,7 +991,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// string literal patterns to have type `str`. This is accounted for when lowering to MIR.
if self.tcx.features().deref_patterns()
&& matches!(lit_kind, ast::LitKind::Str(..))
&& self.try_structurally_resolve_type(span, expected).is_str()
&& self.resolve_vars_with_obligations(expected).is_str()
{
pat_ty = self.tcx.types.str_;
}
@@ -1032,7 +1032,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// be peeled to `str` while ty here is still `&str`, if we don't
// err early here, a rather confusing unification error will be
// emitted instead).
let ty = self.try_structurally_resolve_type(expr.span, ty);
let ty = self.resolve_vars_with_obligations(ty);
let fail =
!(ty.is_numeric() || ty.is_char() || ty.is_ty_var() || ty.references_error());
Some((fail, ty, expr.span))
@@ -2705,7 +2705,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
[source_ty],
);
let target_ty = self.normalize(span, Unnormalized::new_wip(target_ty));
self.try_structurally_resolve_type(span, target_ty)
self.resolve_vars_with_obligations(target_ty)
}
/// Check if the interior of a deref pattern (either explicit or implicit) has any `ref mut`
@@ -2753,7 +2753,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(pat_prefix_span);
}
expected = self.try_structurally_resolve_type(pat.span, expected);
expected = self.resolve_vars_with_obligations(expected);
// Determine whether we're consuming an inherited reference and resetting the default
// binding mode, based on edition and enabled experimental features.
if let ByRef::Yes(inh_pin, inh_mut) = pat_info.binding_mode
@@ -3044,7 +3044,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Ty<'tcx>,
pat_info: PatInfo<'tcx>,
) -> Ty<'tcx> {
let expected = self.try_structurally_resolve_type(span, expected);
let expected = self.resolve_vars_with_obligations(expected);
// If the pattern is irrefutable and `expected` is an infer ty, we try to equate it
// to an array if the given pattern allows it. See issue #76342
+5 -46
View File
@@ -49,9 +49,7 @@ use rustc_middle::ty::{
use rustc_middle::{bug, span_bug};
use rustc_session::lint;
use rustc_span::{BytePos, Pos, Span, Symbol, sym};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt as _;
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::solve;
use tracing::{debug, instrument};
use super::FnCtxt;
@@ -1172,45 +1170,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
}
}
fn normalize_capture_place(&self, span: Span, place: Place<'tcx>) -> Place<'tcx> {
let mut place = self.resolve_vars_if_possible(place);
// In the new solver, types in HIR `Place`s can contain unnormalized aliases,
// which can ICE later (e.g. when projecting fields for diagnostics).
if self.next_trait_solver() {
let cause = self.misc(span);
let at = self.at(&cause, self.param_env);
match solve::deeply_normalize_with_skipped_universes_and_ambiguous_coroutine_goals(
at,
Unnormalized::new_wip(place.clone()),
vec![],
) {
Ok((normalized, goals)) => {
if !goals.is_empty() {
let mut typeck_results = self.typeck_results.borrow_mut();
typeck_results.coroutine_stalled_predicates.extend(
goals
.into_iter()
// FIXME: throwing away the param-env :(
.map(|goal| (goal.predicate, self.misc(span))),
);
}
normalized
}
Err(errors) => {
let guar = self.infcx.err_ctxt().report_fulfillment_errors(errors);
place.base_ty = Ty::new_error(self.tcx, guar);
for proj in &mut place.projections {
proj.ty = Ty::new_error(self.tcx, guar);
}
place
}
}
} else {
// For the old solver we can rely on `normalize` to eagerly normalize aliases.
self.normalize(span, Unnormalized::new_wip(place))
}
}
/// Combines all the reasons for 2229 migrations
fn compute_2229_migrations_reasons(
@@ -1828,7 +1787,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Normalize eagerly when inserting into `capture_information`, so all downstream
// capture analysis can assume a normalized `Place`.
self.normalize_capture_place(self.tcx.hir_span(var_hir_id), place)
self.normalize(self.tcx.hir_span(var_hir_id), Unnormalized::new_wip(place))
}
fn should_log_capture_analysis(&self, closure_def_id: LocalDefId) -> bool {
@@ -2134,7 +2093,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
let dummy_capture_kind = ty::UpvarCapture::ByRef(ty::BorrowKind::Immutable);
let span = self.fcx.tcx.hir_span(diag_expr_id);
let place = self.fcx.normalize_capture_place(span, place_with_id.place.clone());
let place = self.fcx.normalize(span, Unnormalized::new_wip(place_with_id.place.clone()));
let (place, _) = restrict_capture_precision(place, dummy_capture_kind);
@@ -2148,7 +2107,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
assert_eq!(self.closure_def_id, upvar_id.closure_expr_id);
let span = self.fcx.tcx.hir_span(diag_expr_id);
let place = self.fcx.normalize_capture_place(span, place_with_id.place.clone());
let place = self.fcx.normalize(span, Unnormalized::new_wip(place_with_id.place.clone()));
self.capture_information.push((
place,
@@ -2166,7 +2125,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
assert_eq!(self.closure_def_id, upvar_id.closure_expr_id);
let span = self.fcx.tcx.hir_span(diag_expr_id);
let place = self.fcx.normalize_capture_place(span, place_with_id.place.clone());
let place = self.fcx.normalize(span, Unnormalized::new_wip(place_with_id.place.clone()));
self.capture_information.push((
place,
@@ -2192,7 +2151,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'tcx> {
let capture_kind = ty::UpvarCapture::ByRef(bk);
let span = self.fcx.tcx.hir_span(diag_expr_id);
let place = self.fcx.normalize_capture_place(span, place_with_id.place.clone());
let place = self.fcx.normalize(span, Unnormalized::new_wip(place_with_id.place.clone()));
// We only want repr packed restriction to be applied to reading references into a packed
// struct, and not when the data is being moved. Therefore we call this method here instead
@@ -13,6 +13,7 @@
pub mod canonical;
pub mod coherence;
pub mod delegate;
pub mod normalize;
pub mod placeholder;
pub mod resolve;
pub mod solve;
@@ -0,0 +1,242 @@
use rustc_type_ir::data_structures::ensure_sufficient_stack;
use rustc_type_ir::inherent::*;
use rustc_type_ir::solve::{Goal, NoSolution};
use rustc_type_ir::{
self as ty, Binder, FallibleTypeFolder, InferConst, InferCtxtLike, InferTy, Interner,
TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
TypeVisitor, UniverseIndex,
};
use tracing::instrument;
use crate::placeholder::{BoundVarReplacer, PlaceholderReplacer};
/// This folder normalizes value and collects ambiguous goals.
///
/// Note that for ambiguous alias which contains escaping bound vars,
/// we just return the original alias and don't collect the ambiguous goal.
pub struct NormalizationFolder<'a, Infcx, I, F>
where
Infcx: InferCtxtLike<Interner = I>,
I: Interner,
{
infcx: &'a Infcx,
universes: Vec<Option<UniverseIndex>>,
stalled_goals: Vec<Goal<I, I::Predicate>>,
normalize: F,
}
#[derive(PartialEq, Eq)]
enum HasEscapingBoundVars {
Yes,
No,
}
/// Finds the max universe present in infer vars.
struct MaxUniverse<'a, Infcx, I>
where
Infcx: InferCtxtLike<Interner = I>,
I: Interner,
{
infcx: &'a Infcx,
max_universe: ty::UniverseIndex,
}
impl<'a, Infcx, I> MaxUniverse<'a, Infcx, I>
where
Infcx: InferCtxtLike<Interner = I>,
I: Interner,
{
fn new(infcx: &'a Infcx) -> Self {
MaxUniverse { infcx, max_universe: ty::UniverseIndex::ROOT }
}
fn max_universe(self) -> ty::UniverseIndex {
self.max_universe
}
}
impl<'a, Infcx, I> TypeVisitor<I> for MaxUniverse<'a, Infcx, I>
where
Infcx: InferCtxtLike<Interner = I>,
I: Interner,
{
type Result = ();
fn visit_ty(&mut self, t: I::Ty) {
if !t.has_infer() {
return;
}
if let ty::Infer(InferTy::TyVar(vid)) = t.kind() {
// We shallow resolved the infer var before.
// So it should be a unresolved infer var with an universe.
self.max_universe = self.max_universe.max(self.infcx.universe_of_ty(vid).unwrap());
}
t.super_visit_with(self)
}
fn visit_const(&mut self, c: I::Const) {
if !c.has_infer() {
return;
}
if let ty::ConstKind::Infer(InferConst::Var(vid)) = c.kind() {
// We shallow resolved the infer var before.
// So it should be a unresolved infer var with an universe.
self.max_universe = self.max_universe.max(self.infcx.universe_of_ct(vid).unwrap());
}
c.super_visit_with(self)
}
fn visit_region(&mut self, r: I::Region) {
if let ty::ReVar(vid) = r.kind() {
self.max_universe = self.max_universe.max(self.infcx.universe_of_lt(vid).unwrap());
}
}
}
impl<'a, Infcx, I, F> NormalizationFolder<'a, Infcx, I, F>
where
Infcx: InferCtxtLike<Interner = I>,
I: Interner,
F: FnMut(I::Term) -> Result<(I::Term, Option<Goal<I, I::Predicate>>), NoSolution>,
{
pub fn new(
infcx: &'a Infcx,
universes: Vec<Option<UniverseIndex>>,
stalled_goals: Vec<Goal<I, I::Predicate>>,
normalize: F,
) -> Self {
Self { infcx, universes, stalled_goals, normalize }
}
pub fn stalled_goals(self) -> Vec<Goal<I, I::Predicate>> {
self.stalled_goals
}
fn normalize_alias_term(
&mut self,
alias_term: I::Term,
has_escaping: HasEscapingBoundVars,
) -> Result<I::Term, NoSolution> {
let current_universe = self.infcx.universe();
self.infcx.create_next_universe();
let (normalized, ambig_goal) = (self.normalize)(alias_term)?;
// Return ambiguous higher ranked alias as is, if
// - it contains escaping vars, and
// - the normalized term contains infer vars newly created
// in the normalization above.
// The problem is that they may be resolved to types
// referencing the temporary placeholders.
//
// We can normalize the ambiguous alias again after the binder is instantiated.
if ambig_goal.is_some() && has_escaping == HasEscapingBoundVars::Yes {
let mut visitor = MaxUniverse::new(self.infcx);
normalized.visit_with(&mut visitor);
let max_universe = visitor.max_universe();
if current_universe.cannot_name(max_universe) {
return Ok(alias_term);
}
}
self.stalled_goals.extend(ambig_goal);
Ok(normalized)
}
}
impl<'a, Infcx, I, F> FallibleTypeFolder<I> for NormalizationFolder<'a, Infcx, I, F>
where
Infcx: InferCtxtLike<Interner = I>,
I: Interner,
F: FnMut(I::Term) -> Result<(I::Term, Option<Goal<I, I::Predicate>>), NoSolution>,
{
type Error = NoSolution;
fn cx(&self) -> I {
self.infcx.cx()
}
fn try_fold_binder<T: TypeFoldable<I>>(
&mut self,
t: Binder<I, T>,
) -> Result<Binder<I, T>, Self::Error> {
self.universes.push(None);
let t = t.try_super_fold_with(self)?;
self.universes.pop();
Ok(t)
}
#[instrument(level = "trace", skip(self), ret)]
fn try_fold_ty(&mut self, ty: I::Ty) -> Result<I::Ty, Self::Error> {
let infcx = self.infcx;
if !ty.has_aliases() {
return Ok(ty);
}
// With eager normalization, we should normalize the args of alias before
// normalizing the alias itself.
let ty = ty.try_super_fold_with(self)?;
let ty::Alias(..) = ty.kind() else { return Ok(ty) };
if ty.has_escaping_bound_vars() {
let (ty, mapped_regions, mapped_types, mapped_consts) =
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ty);
let result = ensure_sufficient_stack(|| {
self.normalize_alias_term(ty.into(), HasEscapingBoundVars::Yes)
})?
.expect_ty();
Ok(PlaceholderReplacer::replace_placeholders(
infcx,
mapped_regions,
mapped_types,
mapped_consts,
&self.universes,
result,
))
} else {
Ok(ensure_sufficient_stack(|| {
self.normalize_alias_term(ty.into(), HasEscapingBoundVars::No)
})?
.expect_ty())
}
}
#[instrument(level = "trace", skip(self), ret)]
fn try_fold_const(&mut self, ct: I::Const) -> Result<I::Const, Self::Error> {
let infcx = self.infcx;
if !ct.has_aliases() {
return Ok(ct);
}
// With eager normalization, we should normalize the args of alias before
// normalizing the alias itself.
let ct = ct.try_super_fold_with(self)?;
let ty::ConstKind::Unevaluated(..) = ct.kind() else { return Ok(ct) };
if ct.has_escaping_bound_vars() {
let (ct, mapped_regions, mapped_types, mapped_consts) =
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ct);
let result = ensure_sufficient_stack(|| {
self.normalize_alias_term(ct.into(), HasEscapingBoundVars::Yes)
})?
.expect_const();
Ok(PlaceholderReplacer::replace_placeholders(
infcx,
mapped_regions,
mapped_types,
mapped_consts,
&self.universes,
result,
))
} else {
Ok(ensure_sufficient_stack(|| {
self.normalize_alias_term(ct.into(), HasEscapingBoundVars::No)
})?
.expect_const())
}
}
}
@@ -6,6 +6,7 @@ use rustc_type_ir::{
self as ty, InferCtxtLike, Interner, PlaceholderConst, PlaceholderRegion, PlaceholderType,
TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
use tracing::debug;
pub struct BoundVarReplacer<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
where
@@ -164,3 +165,155 @@ where
if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
}
}
/// The inverse of [`BoundVarReplacer`]: replaces placeholders with the bound vars from which they came.
pub struct PlaceholderReplacer<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
where
Infcx: InferCtxtLike<Interner = I>,
I: Interner,
{
infcx: &'a Infcx,
mapped_regions: IndexMap<ty::PlaceholderRegion<I>, ty::BoundRegion<I>>,
mapped_types: IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
mapped_consts: IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
universe_indices: &'a [Option<ty::UniverseIndex>],
current_index: ty::DebruijnIndex,
}
impl<'a, Infcx, I> PlaceholderReplacer<'a, Infcx, I>
where
Infcx: InferCtxtLike<Interner = I>,
I: Interner,
{
pub fn replace_placeholders<T: TypeFoldable<I>>(
infcx: &'a Infcx,
mapped_regions: IndexMap<ty::PlaceholderRegion<I>, ty::BoundRegion<I>>,
mapped_types: IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
mapped_consts: IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
universe_indices: &'a [Option<ty::UniverseIndex>],
value: T,
) -> T {
let mut replacer = PlaceholderReplacer {
infcx,
mapped_regions,
mapped_types,
mapped_consts,
universe_indices,
current_index: ty::INNERMOST,
};
value.fold_with(&mut replacer)
}
}
impl<'a, Infcx, I> TypeFolder<I> for PlaceholderReplacer<'a, Infcx, I>
where
Infcx: InferCtxtLike<Interner = I>,
I: Interner,
{
fn cx(&self) -> I {
self.infcx.cx()
}
fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
if !t.has_placeholders() && !t.has_infer() {
return t;
}
self.current_index.shift_in(1);
let t = t.super_fold_with(self);
self.current_index.shift_out(1);
t
}
fn fold_region(&mut self, r0: I::Region) -> I::Region {
let r1 = match r0.kind() {
ty::ReVar(vid) => self.infcx.opportunistic_resolve_lt_var(vid),
_ => r0,
};
let r2 = match r1.kind() {
ty::RePlaceholder(p) => {
let replace_var = self.mapped_regions.get(&p);
match replace_var {
Some(replace_var) => {
let index = self
.universe_indices
.iter()
.position(|u| matches!(u, Some(pu) if *pu == p.universe))
.unwrap_or_else(|| panic!("Unexpected placeholder universe."));
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
Region::new_bound(self.cx(), db, *replace_var)
}
None => r1,
}
}
_ => r1,
};
debug!(?r0, ?r1, ?r2, "fold_region");
r2
}
fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
let ty = self.infcx.shallow_resolve(ty);
match ty.kind() {
ty::Placeholder(p) => {
let replace_var = self.mapped_types.get(&p);
match replace_var {
Some(replace_var) => {
let index = self
.universe_indices
.iter()
.position(|u| matches!(u, Some(pu) if *pu == p.universe))
.unwrap_or_else(|| panic!("Unexpected placeholder universe."));
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
Ty::new_bound(self.infcx.cx(), db, *replace_var)
}
None => {
if ty.has_infer() {
ty.super_fold_with(self)
} else {
ty
}
}
}
}
_ if ty.has_placeholders() || ty.has_infer() => ty.super_fold_with(self),
_ => ty,
}
}
fn fold_const(&mut self, ct: I::Const) -> I::Const {
let ct = self.infcx.shallow_resolve_const(ct);
if let ty::ConstKind::Placeholder(p) = ct.kind() {
let replace_var = self.mapped_consts.get(&p);
match replace_var {
Some(replace_var) => {
let index = self
.universe_indices
.iter()
.position(|u| matches!(u, Some(pu) if *pu == p.universe))
.unwrap_or_else(|| panic!("Unexpected placeholder universe."));
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
Const::new_bound(self.infcx.cx(), db, *replace_var)
}
None => {
if ct.has_infer() {
ct.super_fold_with(self)
} else {
ct
}
}
}
} else {
ct.super_fold_with(self)
}
}
}
@@ -1586,13 +1586,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|alias_term: ty::AliasTerm<'tcx>, expected_term: ty::Term<'tcx>| {
let ocx = ObligationCtxt::new(self);
let Ok(normalized_term) = ocx.structurally_normalize_term(
let normalized_term = ocx.normalize(
&ObligationCause::dummy(),
obligation.param_env,
Unnormalized::new_wip(alias_term.to_term(self.tcx)),
) else {
return None;
};
);
if let Err(terr) = ocx.eq(
&ObligationCause::dummy(),
@@ -2859,13 +2857,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
);
let trait_ref = normalized_predicate.trait_ref;
let Ok(assume) = ocx.structurally_normalize_const(
let assume = ocx.normalize(
&obligation.cause,
obligation.param_env,
Unnormalized::new_wip(trait_ref.args.const_at(2)),
) else {
return (obligation.clone(), trait_predicate);
};
);
let Some(assume) = rustc_transmute::Assume::from_const(self.tcx, assume) else {
return (obligation.clone(), trait_predicate);
@@ -2912,17 +2908,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
);
let ocx = ObligationCtxt::new(self);
let Ok(assume) = ocx.structurally_normalize_const(
let assume = ocx.normalize(
&obligation.cause,
obligation.param_env,
Unnormalized::new_wip(trait_pred.trait_ref.args.const_at(2)),
) else {
self.dcx().span_delayed_bug(
span,
"Unable to construct rustc_transmute::Assume where it was previously possible",
);
return GetSafeTransmuteErrorAndReason::Silent;
};
);
let Some(assume) = rustc_transmute::Assume::from_const(self.infcx.tcx, assume) else {
self.dcx().span_delayed_bug(
+1 -1
View File
@@ -11,7 +11,7 @@ pub use fulfill::{FulfillmentCtxt, NextSolverError};
pub(crate) use normalize::deeply_normalize_for_diagnostics;
pub use normalize::{
deeply_normalize, deeply_normalize_with_skipped_universes,
deeply_normalize_with_skipped_universes_and_ambiguous_coroutine_goals,
deeply_normalize_with_skipped_universes_and_ambiguous_coroutine_goals, normalize,
};
use rustc_middle::query::Providers;
use rustc_middle::ty::TyCtxt;
@@ -1,21 +1,158 @@
use std::fmt::Debug;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_infer::infer::InferCtxt;
use rustc_infer::infer::at::At;
use rustc_infer::traits::solve::Goal;
use rustc_infer::traits::{FromSolverError, Obligation, TraitEngine};
use rustc_infer::traits::{
FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine,
};
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::{
self, FallibleTypeFolder, Flags, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitableExt, UniverseIndex, Unnormalized,
self, Binder, Flags, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
UniverseIndex, Unnormalized,
};
use tracing::instrument;
use rustc_next_trait_solver::normalize::NormalizationFolder;
use rustc_next_trait_solver::solve::SolverDelegateEvalExt;
use super::{FulfillmentCtxt, NextSolverError};
use crate::error_reporting::InferCtxtErrorExt;
use crate::error_reporting::traits::OverflowCause;
use crate::traits::{BoundVarReplacer, PlaceholderReplacer, ScrubbedTraitError};
use crate::solve::{Certainty, SolverDelegate};
use crate::traits::{BoundVarReplacer, ScrubbedTraitError};
/// see `normalize_with_universes`.
pub fn normalize<'tcx, T>(at: At<'_, 'tcx>, value: Unnormalized<'tcx, T>) -> Normalized<'tcx, T>
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
normalize_with_universes(at, value, vec![])
}
/// Like `deeply_normalize`, but we handle ambiguity and inference variables in this routine.
/// The behavior should be same as the old solver.
/// For error, we return an infer var plus the failed obligation.
/// For ambiguity, we have two cases:
/// - has_escaping_bound_vars: return the original alias.
/// - otherwise: return the normalized result. It can be (partially) inferred
/// even if the evaluation result is ambiguous.
fn normalize_with_universes<'tcx, T>(
at: At<'_, 'tcx>,
value: Unnormalized<'tcx, T>,
universes: Vec<Option<UniverseIndex>>,
) -> Normalized<'tcx, T>
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
let infcx = at.infcx;
let value = value.skip_normalization();
let value = infcx.resolve_vars_if_possible(value);
let original_value = value.clone();
let mut folder =
NormalizationFolder::new(infcx, universes.clone(), Default::default(), |alias_term| {
let delegate = <&SolverDelegate<'tcx>>::from(infcx);
let infer_term = delegate.next_term_var_of_kind(alias_term, at.cause.span);
let predicate = ty::PredicateKind::AliasRelate(
alias_term.into(),
infer_term.into(),
ty::AliasRelationDirection::Equate,
);
let goal = Goal::new(infcx.tcx, at.param_env, predicate);
let result = delegate.evaluate_root_goal(goal, at.cause.span, None)?;
let normalized = infcx.resolve_vars_if_possible(infer_term);
let stalled_goal = match result.certainty {
Certainty::Yes => None,
Certainty::Maybe { .. } => Some(infcx.resolve_vars_if_possible(result.goal)),
};
Ok((normalized, stalled_goal))
});
if let Ok(value) = value.try_fold_with(&mut folder) {
let obligations = folder
.stalled_goals()
.into_iter()
.map(|goal| {
Obligation::new(infcx.tcx, at.cause.clone(), goal.param_env, goal.predicate)
})
.collect();
Normalized { value, obligations }
} else {
let mut replacer = ReplaceAliasWithInfer { at, obligations: Default::default(), universes };
let value = original_value.fold_with(&mut replacer);
Normalized { value, obligations: replacer.obligations }
}
}
struct ReplaceAliasWithInfer<'me, 'tcx> {
at: At<'me, 'tcx>,
obligations: PredicateObligations<'tcx>,
universes: Vec<Option<UniverseIndex>>,
}
impl<'me, 'tcx> ReplaceAliasWithInfer<'me, 'tcx> {
fn term_to_infer(&mut self, alias_term: ty::Term<'tcx>) -> ty::Term<'tcx> {
let infcx = self.at.infcx;
let infer_term = infcx.next_term_var_of_kind(alias_term, self.at.cause.span);
let obligation = Obligation::new(
infcx.tcx,
self.at.cause.clone(),
self.at.param_env,
ty::PredicateKind::AliasRelate(
alias_term.into(),
infer_term.into(),
ty::AliasRelationDirection::Equate,
),
);
self.obligations.push(obligation);
infer_term
}
}
impl<'me, 'tcx> TypeFolder<TyCtxt<'tcx>> for ReplaceAliasWithInfer<'me, 'tcx> {
fn cx(&self) -> TyCtxt<'tcx> {
self.at.infcx.tcx
}
fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: Binder<'tcx, T>,
) -> Binder<'tcx, T> {
self.universes.push(None);
let t = t.super_fold_with(self);
self.universes.pop();
t
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if !ty.has_aliases() {
return ty;
}
let ty = ty.super_fold_with(self);
let ty::Alias(..) = *ty.kind() else { return ty };
if ty.has_escaping_bound_vars() {
let (replaced, ..) =
BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, ty);
let _ = self.term_to_infer(replaced.into());
ty
} else {
self.term_to_infer(ty.into()).expect_type()
}
}
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
if !ct.has_aliases() {
return ct;
}
let ct = ct.super_fold_with(self);
let ty::ConstKind::Unevaluated(..) = ct.kind() else { return ct };
if ct.has_escaping_bound_vars() {
let (replaced, ..) =
BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, ct);
let _ = self.term_to_infer(replaced.into());
ct
} else {
self.term_to_infer(ct.into()).expect_const()
}
}
}
/// Deeply normalize all aliases in `value`. This does not handle inference and expects
/// its input to be already fully resolved.
@@ -73,177 +210,30 @@ where
T: TypeFoldable<TyCtxt<'tcx>>,
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
{
let value = value.skip_normalization();
let fulfill_cx = FulfillmentCtxt::new(at.infcx);
let mut folder = NormalizationFolder {
at,
fulfill_cx,
depth: 0,
universes,
stalled_coroutine_goals: vec![],
};
let value = value.try_fold_with(&mut folder)?;
let errors = folder.fulfill_cx.evaluate_obligations_error_on_ambiguity(at.infcx);
if errors.is_empty() { Ok((value, folder.stalled_coroutine_goals)) } else { Err(errors) }
}
let Normalized { value, obligations } = normalize_with_universes(at, value, universes);
struct NormalizationFolder<'me, 'tcx, E> {
at: At<'me, 'tcx>,
fulfill_cx: FulfillmentCtxt<'tcx, E>,
depth: usize,
universes: Vec<Option<UniverseIndex>>,
stalled_coroutine_goals: Vec<Goal<'tcx, ty::Predicate<'tcx>>>,
}
impl<'tcx, E> NormalizationFolder<'_, 'tcx, E>
where
E: FromSolverError<'tcx, NextSolverError<'tcx>>,
{
fn normalize_alias_term(
&mut self,
alias_term: ty::Term<'tcx>,
) -> Result<ty::Term<'tcx>, Vec<E>> {
let infcx = self.at.infcx;
let tcx = infcx.tcx;
let recursion_limit = tcx.recursion_limit();
if !recursion_limit.value_within_limit(self.depth) {
let term = alias_term.to_alias_term(tcx).unwrap();
self.at.infcx.err_ctxt().report_overflow_error(
OverflowCause::DeeplyNormalize(term),
self.at.cause.span,
true,
|_| {},
);
}
self.depth += 1;
let infer_term = infcx.next_term_var_of_kind(alias_term, self.at.cause.span);
let obligation = Obligation::new(
tcx,
self.at.cause.clone(),
self.at.param_env,
ty::PredicateKind::AliasRelate(
alias_term.into(),
infer_term.into(),
ty::AliasRelationDirection::Equate,
),
);
self.fulfill_cx.register_predicate_obligation(infcx, obligation);
self.evaluate_all_error_on_ambiguity_stall_coroutine_predicates()?;
// Alias is guaranteed to be fully structurally resolved,
// so we can super fold here.
let term = infcx.resolve_vars_if_possible(infer_term);
// super-folding the `term` will directly fold the `Ty` or `Const` so
// we have to match on the term and super-fold them manually.
let result = match term.kind() {
ty::TermKind::Ty(ty) => ty.try_super_fold_with(self)?.into(),
ty::TermKind::Const(ct) => ct.try_super_fold_with(self)?.into(),
};
self.depth -= 1;
Ok(result)
let mut fulfill_cx = FulfillmentCtxt::new(at.infcx);
for pred in obligations {
fulfill_cx.register_predicate_obligation(at.infcx, pred);
}
fn evaluate_all_error_on_ambiguity_stall_coroutine_predicates(&mut self) -> Result<(), Vec<E>> {
let errors = self.fulfill_cx.try_evaluate_obligations(self.at.infcx);
if !errors.is_empty() {
return Err(errors);
}
self.stalled_coroutine_goals.extend(
self.fulfill_cx
.drain_stalled_obligations_for_coroutines(self.at.infcx)
.into_iter()
.map(|obl| obl.as_goal()),
);
let errors = self.fulfill_cx.collect_remaining_errors(self.at.infcx);
if !errors.is_empty() {
return Err(errors);
}
Ok(())
}
}
impl<'tcx, E> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx, E>
where
E: FromSolverError<'tcx, NextSolverError<'tcx>> + Debug,
{
type Error = Vec<E>;
fn cx(&self) -> TyCtxt<'tcx> {
self.at.infcx.tcx
let errors = fulfill_cx.try_evaluate_obligations(at.infcx);
if !errors.is_empty() {
return Err(errors);
}
fn try_fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> Result<ty::Binder<'tcx, T>, Self::Error> {
self.universes.push(None);
let t = t.try_super_fold_with(self)?;
self.universes.pop();
Ok(t)
let stalled_coroutine_goals = fulfill_cx
.drain_stalled_obligations_for_coroutines(at.infcx)
.into_iter()
.map(|obl| obl.as_goal())
.collect();
let errors = fulfill_cx.collect_remaining_errors(at.infcx);
if !errors.is_empty() {
return Err(errors);
}
#[instrument(level = "trace", skip(self), ret)]
fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
let infcx = self.at.infcx;
debug_assert_eq!(ty, infcx.shallow_resolve(ty));
if !ty.has_aliases() {
return Ok(ty);
}
let ty::Alias(..) = *ty.kind() else { return ty.try_super_fold_with(self) };
if ty.has_escaping_bound_vars() {
let (ty, mapped_regions, mapped_types, mapped_consts) =
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ty);
let result =
ensure_sufficient_stack(|| self.normalize_alias_term(ty.into()))?.expect_type();
Ok(PlaceholderReplacer::replace_placeholders(
infcx,
mapped_regions,
mapped_types,
mapped_consts,
&self.universes,
result,
))
} else {
Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ty.into()))?.expect_type())
}
}
#[instrument(level = "trace", skip(self), ret)]
fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
let infcx = self.at.infcx;
debug_assert_eq!(ct, infcx.shallow_resolve_const(ct));
if !ct.has_aliases() {
return Ok(ct);
}
let ty::ConstKind::Unevaluated(..) = ct.kind() else { return ct.try_super_fold_with(self) };
if ct.has_escaping_bound_vars() {
let (ct, mapped_regions, mapped_types, mapped_consts) =
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ct);
let result =
ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const();
Ok(PlaceholderReplacer::replace_placeholders(
infcx,
mapped_regions,
mapped_types,
mapped_consts,
&self.universes,
result,
))
} else {
Ok(ensure_sufficient_stack(|| self.normalize_alias_term(ct.into()))?.expect_const())
}
}
Ok((value, stalled_coroutine_goals))
}
// Deeply normalize a value and return it
@@ -258,7 +258,11 @@ fn do_normalize_predicates<'tcx>(
elaborated_env: ty::ParamEnv<'tcx>,
predicates: Vec<ty::Clause<'tcx>>,
) -> Result<Vec<ty::Clause<'tcx>>, ErrorGuaranteed> {
let span = cause.span;
// Even if we move back to eager normalization elsewhere,
// param env normalization remains lazy in the next solver.
if tcx.next_trait_solver_globally() {
return Ok(predicates);
}
// FIXME. We should really... do something with these region
// obligations. But this call just continues the older
@@ -273,6 +277,7 @@ fn do_normalize_predicates<'tcx>(
// by wfcheck anyway, so I'm not sure we have to check
// them here too, and we will remove this function when
// we move over to lazy normalization *anyway*.
let span = cause.span;
let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
let predicates = ocx.normalize(&cause, elaborated_env, Unnormalized::new_wip(predicates));
@@ -32,10 +32,11 @@ impl<'tcx> At<'_, 'tcx> {
&self,
value: Unnormalized<'tcx, T>,
) -> InferOk<'tcx, T> {
let value = value.skip_normalization();
if self.infcx.next_trait_solver() {
InferOk { value, obligations: PredicateObligations::new() }
let Normalized { value, obligations } = crate::solve::normalize(*self, value);
InferOk { value, obligations }
} else {
let value = value.skip_normalization();
let mut selcx = SelectionContext::new(self.infcx);
let Normalized { value, obligations } =
normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value);
@@ -158,7 +158,12 @@ where
root_def_id,
"query type op",
span,
|ocx| QueryTypeOp::perform_locally_with_next_solver(ocx, self, span),
|ocx| {
if let Some(result) = QueryTypeOp::try_fast_path(infcx.tcx, &self) {
return Ok(result);
}
QueryTypeOp::perform_locally_with_next_solver(ocx, self, span)
},
)?
.0);
}
@@ -29,11 +29,16 @@ where
}
fn perform_locally_with_next_solver(
_ocx: &ObligationCtxt<'_, 'tcx>,
ocx: &ObligationCtxt<'_, 'tcx>,
key: ParamEnvAnd<'tcx, Self>,
_span: Span,
span: Span,
) -> Result<Self::QueryResponse, NoSolution> {
Ok(key.value.value)
ocx.deeply_normalize(
&ObligationCause::dummy_with_span(span),
key.param_env,
Unnormalized::new_wip(key.value.value),
)
.map_err(|_| NoSolution)
}
}
@@ -1,18 +1,17 @@
use std::collections::VecDeque;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::LangItem;
use rustc_hir::def_id::DefId;
use rustc_infer::infer::InferCtxt;
use rustc_infer::traits::PolyTraitObligation;
pub use rustc_infer::traits::util::*;
use rustc_middle::bug;
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::{
self, PolyTraitPredicate, PredicatePolarity, SizedTraitKind, TraitPredicate, TraitRef, Ty,
TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, Unnormalized,
TyCtxt, TypeFoldable, TypeVisitableExt, Unnormalized,
};
pub use rustc_next_trait_solver::placeholder::BoundVarReplacer;
pub use rustc_next_trait_solver::placeholder::{BoundVarReplacer, PlaceholderReplacer};
use rustc_span::Span;
use smallvec::{SmallVec, smallvec};
use tracing::debug;
@@ -218,154 +217,6 @@ pub fn with_replaced_escaping_bound_vars<
}
}
/// The inverse of [`BoundVarReplacer`]: replaces placeholders with the bound vars from which they came.
pub struct PlaceholderReplacer<'a, 'tcx> {
infcx: &'a InferCtxt<'tcx>,
mapped_regions: FxIndexMap<ty::PlaceholderRegion<'tcx>, ty::BoundRegion<'tcx>>,
mapped_types: FxIndexMap<ty::PlaceholderType<'tcx>, ty::BoundTy<'tcx>>,
mapped_consts: FxIndexMap<ty::PlaceholderConst<'tcx>, ty::BoundConst<'tcx>>,
universe_indices: &'a [Option<ty::UniverseIndex>],
current_index: ty::DebruijnIndex,
}
impl<'a, 'tcx> PlaceholderReplacer<'a, 'tcx> {
pub fn replace_placeholders<T: TypeFoldable<TyCtxt<'tcx>>>(
infcx: &'a InferCtxt<'tcx>,
mapped_regions: FxIndexMap<ty::PlaceholderRegion<'tcx>, ty::BoundRegion<'tcx>>,
mapped_types: FxIndexMap<ty::PlaceholderType<'tcx>, ty::BoundTy<'tcx>>,
mapped_consts: FxIndexMap<ty::PlaceholderConst<'tcx>, ty::BoundConst<'tcx>>,
universe_indices: &'a [Option<ty::UniverseIndex>],
value: T,
) -> T {
let mut replacer = PlaceholderReplacer {
infcx,
mapped_regions,
mapped_types,
mapped_consts,
universe_indices,
current_index: ty::INNERMOST,
};
value.fold_with(&mut replacer)
}
}
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
fn cx(&self) -> TyCtxt<'tcx> {
self.infcx.tcx
}
fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
if !t.has_placeholders() && !t.has_infer() {
return t;
}
self.current_index.shift_in(1);
let t = t.super_fold_with(self);
self.current_index.shift_out(1);
t
}
fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> {
let r1 = match r0.kind() {
ty::ReVar(vid) => self
.infcx
.inner
.borrow_mut()
.unwrap_region_constraints()
.opportunistic_resolve_var(self.infcx.tcx, vid),
_ => r0,
};
let r2 = match r1.kind() {
ty::RePlaceholder(p) => {
let replace_var = self.mapped_regions.get(&p);
match replace_var {
Some(replace_var) => {
let index = self
.universe_indices
.iter()
.position(|u| matches!(u, Some(pu) if *pu == p.universe))
.unwrap_or_else(|| bug!("Unexpected placeholder universe."));
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
ty::Region::new_bound(self.cx(), db, *replace_var)
}
None => r1,
}
}
_ => r1,
};
debug!(?r0, ?r1, ?r2, "fold_region");
r2
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
let ty = self.infcx.shallow_resolve(ty);
match *ty.kind() {
ty::Placeholder(p) => {
let replace_var = self.mapped_types.get(&p);
match replace_var {
Some(replace_var) => {
let index = self
.universe_indices
.iter()
.position(|u| matches!(u, Some(pu) if *pu == p.universe))
.unwrap_or_else(|| bug!("Unexpected placeholder universe."));
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
Ty::new_bound(self.infcx.tcx, db, *replace_var)
}
None => {
if ty.has_infer() {
ty.super_fold_with(self)
} else {
ty
}
}
}
}
_ if ty.has_placeholders() || ty.has_infer() => ty.super_fold_with(self),
_ => ty,
}
}
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
let ct = self.infcx.shallow_resolve_const(ct);
if let ty::ConstKind::Placeholder(p) = ct.kind() {
let replace_var = self.mapped_consts.get(&p);
match replace_var {
Some(replace_var) => {
let index = self
.universe_indices
.iter()
.position(|u| matches!(u, Some(pu) if *pu == p.universe))
.unwrap_or_else(|| bug!("Unexpected placeholder universe."));
let db = ty::DebruijnIndex::from_usize(
self.universe_indices.len() - index + self.current_index.as_usize() - 1,
);
ty::Const::new_bound(self.infcx.tcx, db, *replace_var)
}
None => {
if ct.has_infer() {
ct.super_fold_with(self)
} else {
ct
}
}
}
} else {
ct.super_fold_with(self)
}
}
}
pub fn sizedness_fast_path<'tcx>(
tcx: TyCtxt<'tcx>,
predicate: ty::Predicate<'tcx>,
+2 -8
View File
@@ -362,14 +362,8 @@ fn impl_self_is_guaranteed_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId)
tcx.type_of(impl_def_id).instantiate_identity().skip_norm_wip(),
&cause,
|ty| {
ocx.structurally_normalize_ty(&cause, param_env, Unnormalized::new_wip(ty))
.unwrap_or_else(|_| {
Ty::new_error_with_message(
tcx,
tcx.def_span(impl_def_id),
"struct tail should be computable",
)
})
// FIXME: ambiguity is just ignored.
ocx.normalize(&cause, param_env, Unnormalized::new_wip(ty))
},
|| (),
);
-42
View File
@@ -1,42 +0,0 @@
//@ known-bug: #101557
//@ compile-flags: -Copt-level=0
#![feature(generic_const_exprs)]
use std::marker::PhantomData;
trait Trait {
const CONST: usize;
}
struct A<T: Trait> {
_marker: PhantomData<T>,
}
impl<const N: usize> Trait for [i8; N] {
const CONST: usize = N;
}
impl<const N: usize> From<usize> for A<[i8; N]> {
fn from(_: usize) -> Self {
todo!()
}
}
impl<T: Trait> From<A<[i8; T::CONST]>> for A<T> {
fn from(_: A<[i8; T::CONST]>) -> Self {
todo!()
}
}
fn f<T: Trait>() -> A<T>
where
[(); T::CONST]:,
{
// Usage of `0` is arbitrary
let a = A::<[i8; T::CONST]>::from(0);
A::<T>::from(a)
}
fn main() {
// Usage of `1` is arbitrary
f::<[i8; 1]>();
}
-48
View File
@@ -1,48 +0,0 @@
//@ known-bug: #119692
//@ compile-flags: -Copt-level=0
#![allow(incomplete_features)]
#![feature(adt_const_params)]
#![feature(generic_const_exprs)]
use std::ops::Add;
#[derive(PartialEq, Eq, Clone, Debug, core::marker::ConstParamTy)]
pub struct Dimension;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Default)]
pub struct Quantity<S, const D: Dimension>(pub(crate) S);
impl<const D: Dimension, LHS, RHS> Add<Quantity<RHS, D>> for Quantity<LHS, D>
where
LHS: Add<RHS>,
{
type Output = Quantity<<LHS as Add<RHS>>::Output, D>;
fn add(self, rhs: Quantity<RHS, D>) -> Self::Output {
Quantity(self.0 + rhs.0)
}
}
impl<LHS, RHS> Add<RHS> for Quantity<LHS, { Dimension }>
where
LHS: Add<RHS>,
{
type Output = Quantity<<LHS as Add<RHS>>::Output, { Dimension }>;
fn add(self, rhs: RHS) -> Self::Output {
Quantity(self.0 + rhs)
}
}
impl Add<Quantity<f32, { Dimension }>> for f32 {
type Output = Quantity<f32, { Dimension }>;
fn add(self, rhs: Quantity<f32, { Dimension }>) -> Self::Output {
Quantity(self + rhs.0)
}
}
pub fn add<const U: Dimension>(x: Quantity<f32, U>, y: Quantity<f32, U>) -> Quantity<f32, U> {
x + y
}
fn main() {
add(Quantity::<f32, {Dimension}>(1.0), Quantity(2.0));
}
-27
View File
@@ -1,27 +0,0 @@
//@ known-bug: #136859
#![feature(generic_const_exprs)]
trait If<const COND: bool> {}
impl If<true> for () {}
trait IsZero<const N: u8> {
type Answer;
}
struct True;
struct False;
impl<const N: u8> IsZero<N> for ()
where (): If<{N == 0}> {
type Msg = True;
}
trait Foobar<const N: u8> {}
impl<const N: u8> Foobar<N> for ()
where (): IsZero<N, Answer = True> {}
impl<const N: u8> Foobar<{{ N }}> for ()
where (): IsZero<N, Answer = False> {}
fn main() {}
@@ -1,12 +1,14 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@ ignore-compare-mode-next-solver (explicit revisions)
//@ known-bug: #155761
//@compile-flags: -Znext-solver
// A regression test for https://github.com/rust-lang/rust/issues/151329.
// Ensures we do not trigger an ICE when normalization fails for a
// projection on a trait object, even if the projection has the same
// trait id as the object's bound.
// ICE again after moving to eager normalization in the next solver.
// #155761 has a simplified variant which causes ICE without eager normalization.
trait Foo {
type V;
}
@@ -18,12 +20,8 @@ struct Bar<T: Foo + ?Sized> {
}
impl<T: Foo> Bar<dyn Callback<T>> {
//~^ ERROR: the trait bound `(dyn Callback<T> + 'static): Foo` is not satisfied
fn event(&self) {
//~^ ERROR: the trait bound `(dyn Callback<T> + 'static): Foo` is not satisfied
(self.callback)(any(), any());
//~^ ERROR: the trait bound `(dyn Callback<T> + 'static): Foo` is not satisfied
//~| ERROR: expected function
}
}
@@ -11,10 +11,7 @@ LL | fn ret_ref_local<'e>() -> &'e i32 {
| ------- expected `&'e i32` because of return type
...
LL | f(&1)
| ^^^^^ expected `&i32`, found associated type
|
= help: consider constraining the associated type `S<'_>::P` to `&'e i32`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
| ^^^^^ expected `&i32`, found `()`
error: aborting due to 2 previous errors
@@ -46,16 +46,17 @@ LL | type AssocType = impl Send;
error[E0308]: mismatched types
--> $DIR/next-solver-opaque-inherent-fn-ptr-issue-155204.rs:14:9
|
LL | type AssocType = impl Send;
| --------- the expected opaque type
...
LL | fn ret(&self) -> Self::AssocType {
| --------------- expected `Windows<for<'a> fn(&'a ())>::AssocType` because of return type
LL |
LL | ()
| ^^ types differ
|
= note: expected associated type `Windows<for<'a> fn(&'a ())>::AssocType`
found unit type `()`
= help: consider constraining the associated type `Windows<for<'a> fn(&'a ())>::AssocType` to `()` or calling a method that returns `Windows<for<'a> fn(&'a ())>::AssocType`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: expected opaque type `Windows<for<'a> fn(&'a ())>::AssocType`
found unit type `()`
error: aborting due to 7 previous errors
@@ -40,15 +40,16 @@ LL | type ImplTrait = impl Clone;
error[E0308]: mismatched types
--> $DIR/next-solver-opaque-inherent-no-ice.rs:13:9
|
LL | type ImplTrait = impl Clone;
| ---------- the expected opaque type
...
LL | fn f() -> Self::ImplTrait {
| --------------- expected `Foo::ImplTrait` because of return type
LL | ()
| ^^ types differ
|
= note: expected associated type `Foo::ImplTrait`
found unit type `()`
= help: consider constraining the associated type `Foo::ImplTrait` to `()` or calling a method that returns `Foo::ImplTrait`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
= note: expected opaque type `Foo::ImplTrait`
found unit type `()`
error: aborting due to 6 previous errors
@@ -1,20 +1,20 @@
error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned`
error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `Cow<'_, _>`
--> $DIR/associated-types-coherence-failure.rs:21:1
|
LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned {
| ----------------------------------------------------------------------------- first implementation here
...
LL | impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Cow<'_, _>`
error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `<_ as ToOwned>::Owned`
error[E0119]: conflicting implementations of trait `IntoCow<'_, _>` for type `&_`
--> $DIR/associated-types-coherence-failure.rs:28:1
|
LL | impl<'a, B: ?Sized> IntoCow<'a, B> for <B as ToOwned>::Owned where B: ToOwned {
| ----------------------------------------------------------------------------- first implementation here
...
LL | impl<'a, B: ?Sized> IntoCow<'a, B> for &'a B where B: ToOwned {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as ToOwned>::Owned`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_`
error: aborting due to 2 previous errors
@@ -8,7 +8,7 @@ error[E0308]: mismatched types
--> $DIR/suggest-param-env-shadowing-incompatible-args.rs:14:9
|
LL | fn foo() -> Self::Assoc {
| ----------- expected `<() as Foo>::Assoc` because of return type
| ----------- expected `u8` because of return type
LL | []
| ^^ expected `u8`, found `[_; 0]`
|
+1 -1
View File
@@ -10,6 +10,6 @@ struct Wrapper<T>(T);
trait Trait {}
impl Trait for Wrapper<OpaqueClosure> {}
impl<T: Sync> Trait for Wrapper<T> {}
//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
//~^ ERROR: conflicting implementations of trait `Trait` for type
fn main() {}
@@ -1,10 +1,10 @@
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<_>`
--> $DIR/coherence-with-closure.rs:12:1
|
LL | impl Trait for Wrapper<OpaqueClosure> {}
| ------------------------------------- first implementation here
LL | impl<T: Sync> Trait for Wrapper<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueClosure>`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<_>`
error: aborting due to 1 previous error
@@ -21,6 +21,6 @@ struct Wrapper<T>(T);
trait Trait {}
impl Trait for Wrapper<OpaqueCoroutine> {}
impl<T: Sync> Trait for Wrapper<T> {}
//[stock]~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueCoroutine>`
//[stock]~^ ERROR: conflicting implementations of trait `Trait` for type
fn main() {}
@@ -1,10 +1,10 @@
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueCoroutine>`
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<_>`
--> $DIR/coherence-with-coroutine.rs:23:1
|
LL | impl Trait for Wrapper<OpaqueCoroutine> {}
| --------------------------------------- first implementation here
LL | impl<T: Sync> Trait for Wrapper<T> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueCoroutine>`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<_>`
error: aborting due to 1 previous error
@@ -1,11 +1,11 @@
error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)`
error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, _)`
--> $DIR/normalize-for-errors.rs:13:1
|
LL | impl<T: Copy, S: Iterator> MyTrait<S> for (T, S::Item) {}
| ------------------------------------------------------ first implementation here
LL |
LL | impl<S: Iterator> MyTrait<S> for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, _)`
|
= note: upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
@@ -26,12 +26,9 @@ mod v20 {
}
impl<const v10: usize> v17<v10, v2> {
//~^ ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
//~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
//~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
//~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
//~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
//~| ERROR maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
//~^ ERROR: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
//~| ERROR: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
//~| ERROR: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
pub const fn v21() -> v18 {
//~^ ERROR cannot find type `v18` in this scope
v18 { _p: () }
@@ -1,5 +1,5 @@
error[E0432]: unresolved import `v20::v13`
--> $DIR/unevaluated-const-ice-119731.rs:42:15
--> $DIR/unevaluated-const-ice-119731.rs:39:15
|
LL | pub use v20::{v13, v17};
| ^^^ no `v13` in `v20`
@@ -32,7 +32,7 @@ LL + pub const fn v21() -> v11 {}
|
error[E0425]: cannot find type `v18` in this scope
--> $DIR/unevaluated-const-ice-119731.rs:35:31
--> $DIR/unevaluated-const-ice-119731.rs:32:31
|
LL | pub type v11 = [[usize; v4]; v4];
| --------------------------------- similarly named type alias `v11` defined here
@@ -47,7 +47,7 @@ LL + pub const fn v21() -> v11 {
|
error[E0422]: cannot find struct, variant or union type `v18` in this scope
--> $DIR/unevaluated-const-ice-119731.rs:37:13
--> $DIR/unevaluated-const-ice-119731.rs:34:13
|
LL | pub type v11 = [[usize; v4]; v4];
| --------------------------------- similarly named type alias `v11` defined here
@@ -115,30 +115,6 @@ LL | impl<const v10: usize> v17<v10, v2> {
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
--> $DIR/unevaluated-const-ice-119731.rs:28:37
|
LL | impl<const v10: usize> v17<v10, v2> {
| ^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
--> $DIR/unevaluated-const-ice-119731.rs:28:37
|
LL | impl<const v10: usize> v17<v10, v2> {
| ^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: maximum number of nodes exceeded in constant v20::v17::<v10, v2>::{constant#0}
--> $DIR/unevaluated-const-ice-119731.rs:28:37
|
LL | impl<const v10: usize> v17<v10, v2> {
| ^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0592]: duplicate definitions with name `v21`
--> $DIR/unevaluated-const-ice-119731.rs:23:9
|
@@ -148,7 +124,7 @@ LL | pub const fn v21() -> v18 {}
LL | pub const fn v21() -> v18 {
| ------------------------- other definition for `v21`
error: aborting due to 14 previous errors; 2 warnings emitted
error: aborting due to 11 previous errors; 2 warnings emitted
Some errors have detailed explanations: E0422, E0425, E0432, E0592.
For more information about an error, try `rustc --explain E0422`.
@@ -1,17 +1,17 @@
//@ check-pass
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
struct GenericStruct<const T: usize> { val: i64 }
impl<const T: usize> From<GenericStruct<T>> for GenericStruct<{T + 1}> {
//~^ ERROR: conflicting implementations of trait `From<GenericStruct<_>>` for type `GenericStruct<_>`
fn from(other: GenericStruct<T>) -> Self {
Self { val: other.val }
}
}
impl<const T: usize> From<GenericStruct<{T + 1}>> for GenericStruct<T> {
//~^ ERROR: conflicting implementations of trait `From<GenericStruct<_>>` for type `GenericStruct<_>`
fn from(other: GenericStruct<{T + 1}>) -> Self {
Self { val: other.val }
}
@@ -0,0 +1,21 @@
error[E0119]: conflicting implementations of trait `From<GenericStruct<_>>` for type `GenericStruct<_>`
--> $DIR/issue-89304.rs:6:1
|
LL | impl<const T: usize> From<GenericStruct<T>> for GenericStruct<{T + 1}> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T> From<T> for T;
error[E0119]: conflicting implementations of trait `From<GenericStruct<_>>` for type `GenericStruct<_>`
--> $DIR/issue-89304.rs:13:1
|
LL | impl<const T: usize> From<GenericStruct<{T + 1}>> for GenericStruct<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T> From<T> for T;
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0119`.
+10 -2
View File
@@ -10,7 +10,11 @@ note: ...which requires comparing an impl and trait method signature, inferring
LL | reuse to_reuse::opaque_ret;
| ^^^^^^^^^^
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:28:5: 28:24>::opaque_ret::{anon_assoc#0}`, completing the cycle
= note: cycle used when computing implied outlives bounds for `<u8 as opaque::ToReuse>::opaque_ret::{anon_assoc#0}` (hack disabled = false)
note: cycle used when checking assoc item `opaque::<impl at $DIR/unsupported.rs:28:5: 28:24>::opaque_ret` is compatible with trait definition
--> $DIR/unsupported.rs:29:25
|
LL | reuse to_reuse::opaque_ret;
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error[E0391]: cycle detected when computing type of `opaque::<impl at $DIR/unsupported.rs:31:5: 31:25>::opaque_ret::{anon_assoc#0}`
@@ -25,7 +29,11 @@ note: ...which requires comparing an impl and trait method signature, inferring
LL | reuse ToReuse::opaque_ret;
| ^^^^^^^^^^
= note: ...which again requires computing type of `opaque::<impl at $DIR/unsupported.rs:31:5: 31:25>::opaque_ret::{anon_assoc#0}`, completing the cycle
= note: cycle used when computing implied outlives bounds for `<u16 as opaque::ToReuse>::opaque_ret::{anon_assoc#0}` (hack disabled = false)
note: cycle used when checking assoc item `opaque::<impl at $DIR/unsupported.rs:31:5: 31:25>::opaque_ret` is compatible with trait definition
--> $DIR/unsupported.rs:32:24
|
LL | reuse ToReuse::opaque_ret;
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
error: aborting due to 2 previous errors
@@ -22,20 +22,6 @@ LL | where
LL | T: AsExpression<Self::SqlType>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::check`
error[E0277]: the trait bound `&str: AsExpression<Integer>` is not satisfied
--> $DIR/as_expression.rs:56:5
|
LL | SelectInt.check("bar");
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `AsExpression<Integer>` is not implemented for `&str`
|
help: the trait `AsExpression<Integer>` is not implemented for `&str`
but trait `AsExpression<Text>` is implemented for it
--> $DIR/as_expression.rs:40:1
|
LL | impl AsExpression<Text> for &'_ str {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: for that trait implementation, expected `Text`, found `Integer`
error: aborting due to 2 previous errors
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.
@@ -55,5 +55,4 @@ impl<T> Foo for T where T: Expression {}
fn main() {
SelectInt.check("bar");
//~^ ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
//[next]~| ERROR the trait bound `&str: AsExpression<Integer>` is not satisfied
}
@@ -1,12 +1,8 @@
error[E0308]: mismatched types
error: higher-ranked subtype error
--> $DIR/must-prove-where-clauses-on-norm.rs:23:61
|
LL | let func: for<'a, 'b> fn((), &'b str) -> &'static str = foo::<()>;
| ^^^^^^^^^ one type is more general than the other
|
= note: expected fn pointer `for<'b> fn((), &'b _) -> &_`
found fn pointer `for<'b> fn((), &'b _) -> &_`
| ^^^^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.
@@ -22,7 +22,7 @@ fn foo<'a, 'b, T: Trait>(_: <T as Trait>::Assoc<'a, 'b>, x: &'b str) -> &'a str
fn main() {
let func: for<'a, 'b> fn((), &'b str) -> &'static str = foo::<()>;
//[current]~^ ERROR higher-ranked lifetime error
//[next]~^^ ERROR mismatched types
//[next]~^^ ERROR higher-ranked subtype error
let x: &'static str = func((), &String::from("temporary"));
println!("{x}");
}
@@ -25,25 +25,13 @@ LL | type LineStream<'c, 'd> = impl Stream;
|
= note: `LineStream` must be used in combination with a concrete type within the same impl
error[E0271]: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to ()`
error[E0271]: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to _`
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:43
|
LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
error[E0271]: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to _`
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:73
|
LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
| ^^ types differ
error[E0271]: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to _`
--> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:5
|
LL | fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
error: aborting due to 6 previous errors
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0049, E0271, E0407.
For more information about an error, try `rustc --explain E0049`.
@@ -29,9 +29,7 @@ impl X for Y {
fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
//~^ ERROR 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> normalizes-to ()`
//[next]~| ERROR type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to _`
//[next]~| ERROR type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to _`
//[next]~^^^ ERROR: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to _`
}
pub fn main() {}
@@ -13,8 +13,6 @@ struct W<T>(T);
// `usize: Foo` doesn't hold. Therefore we ICE, because we don't expect to still
// encounter weak types in `assemble_alias_bound_candidates_recur`.
fn hello(_: W<A<usize>>) {}
//~^ ERROR the trait bound `usize: Foo` is not satisfied
//~| ERROR the trait bound `usize: Foo` is not satisfied
//~| ERROR the trait bound `usize: Foo` is not satisfied
//~^ ERROR: the trait bound `usize: Foo` is not satisfied
//~| ERROR: the trait bound `usize: Foo` is not satisfied
fn main() {}
@@ -16,10 +16,10 @@ LL | type A<T: Foo> = T;
| ^^^ required by this bound in `A`
error[E0277]: the trait bound `usize: Foo` is not satisfied
--> $DIR/alias-bounds-when-not-wf.rs:15:10
--> $DIR/alias-bounds-when-not-wf.rs:15:13
|
LL | fn hello(_: W<A<usize>>) {}
| ^ the trait `Foo` is not implemented for `usize`
| ^^^^^^^^^^^ the trait `Foo` is not implemented for `usize`
|
help: this trait has no implementations, consider adding one
--> $DIR/alias-bounds-when-not-wf.rs:5:1
@@ -27,18 +27,6 @@ help: this trait has no implementations, consider adding one
LL | trait Foo {}
| ^^^^^^^^^
error[E0277]: the trait bound `usize: Foo` is not satisfied
--> $DIR/alias-bounds-when-not-wf.rs:15:1
|
LL | fn hello(_: W<A<usize>>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `usize`
|
help: this trait has no implementations, consider adding one
--> $DIR/alias-bounds-when-not-wf.rs:5:1
|
LL | trait Foo {}
| ^^^^^^^^^
error: aborting due to 3 previous errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.
@@ -1,16 +1,11 @@
error[E0277]: the trait bound `String: Trait<u32>` is not satisfied
--> $DIR/avoid-inference-constraints-from-blanket-3.rs:22:5
--> $DIR/avoid-inference-constraints-from-blanket-3.rs:22:17
|
LL | impls_trait(x);
| ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
| ----------- ^ the trait `Trait<u32>` is not implemented for `String`
| |
| required by a bound introduced by this call
|
help: the trait `Trait<u32>` is not implemented for `String`
but trait `Trait<u64>` is implemented for it
--> $DIR/avoid-inference-constraints-from-blanket-3.rs:17:1
|
LL | impl Trait<u64> for String {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: for that trait implementation, expected `u64`, found `u32`
note: required for `String` to implement `Trait<u32>`
--> $DIR/avoid-inference-constraints-from-blanket-3.rs:16:15
|
@@ -23,6 +18,10 @@ note: required by a bound in `impls_trait`
|
LL | fn impls_trait<T: Trait<U>, U>(_: T) {}
| ^^^^^^^^ required by this bound in `impls_trait`
help: consider borrowing here
|
LL | impls_trait(&x);
| +
error: aborting due to 1 previous error
@@ -16,7 +16,7 @@ LL | fn create_complex_future() -> impl Future<Output = impl ReturnsSend> {
| ^^^^^^^^^^^
error[E0733]: recursion in an async block requires boxing
--> $DIR/ice-issue-146191.rs:8:5
--> $DIR/ice-issue-146191.rs:9:5
|
LL | async { create_complex_future().await }
| ^^^^^ ----------------------------- recursive call here
@@ -1,8 +1,8 @@
error[E0282]: type annotations needed
--> $DIR/ice-issue-146191.rs:8:5
--> $DIR/ice-issue-146191.rs:6:31
|
LL | async { create_complex_future().await }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
LL | fn create_complex_future() -> impl Future<Output = impl ReturnsSend> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
error: aborting due to 1 previous error
@@ -5,9 +5,9 @@
fn create_complex_future() -> impl Future<Output = impl ReturnsSend> {
//[current]~^ ERROR the trait bound `(): ReturnsSend` is not satisfied
//[next]~^^ ERROR type annotations needed
async { create_complex_future().await }
//[current]~^ ERROR recursion in an async block requires
//[next]~^^ ERROR type annotations needed
}
trait ReturnsSend {}
@@ -21,10 +21,10 @@ LL | let (x,): ((_,),) = (build2(x),);
| +++++++++
error[E0282]: type annotations needed
--> $DIR/recursive-in-exhaustiveness.rs:40:5
--> $DIR/recursive-in-exhaustiveness.rs:37:23
|
LL | build3(x)
| ^^^^^^^^^ cannot infer type
LL | fn build3<T>(x: T) -> impl Sized {
| ^^^^^^^^^^ cannot infer type
error: aborting due to 3 previous errors
@@ -36,9 +36,9 @@ fn build2<T>(x: T) -> impl Sized {
// Not allowed today. Detected as not defining.
fn build3<T>(x: T) -> impl Sized {
//[current]~^ ERROR cannot resolve opaque type
//[next]~^^ ERROR type annotations needed
let (x,) = (build3((x,)),);
build3(x)
//[next]~^ ERROR type annotations needed
}
fn main() {}
@@ -1,8 +1,8 @@
error[E0282]: type annotations needed
--> $DIR/two_tait_defining_each_other2.rs:12:8
--> $DIR/two_tait_defining_each_other2.rs:12:11
|
LL | fn muh(x: A) -> B {
| ^ cannot infer type
| ^ cannot infer type
error: aborting due to 1 previous error
@@ -1,11 +1,19 @@
error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
--> $DIR/unsized_coercion.rs:14:17
--> $DIR/unsized_coercion.rs:12:15
|
LL | fn hello() -> Box<impl Trait> {
| ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `dyn Trait`
error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
--> $DIR/unsized_coercion.rs:15: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
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.
+1
View File
@@ -10,6 +10,7 @@ trait Trait {}
impl Trait for u32 {}
fn hello() -> Box<impl Trait> {
//[next]~^ ERROR: the size for values of type `dyn Trait` cannot be known at compilation time
if true {
let x = hello();
//[next]~^ ERROR: the size for values of type `dyn Trait` cannot be known at compilation time
@@ -1,5 +1,17 @@
error[E0277]: the trait bound `dyn Send: Trait` is not satisfied
--> $DIR/unsized_coercion3.rs:13:17
--> $DIR/unsized_coercion3.rs:11:15
|
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[E0277]: the trait bound `dyn Send: Trait` is not satisfied
--> $DIR/unsized_coercion3.rs:14:17
|
LL | let x = hello();
| ^^^^^^^ the trait `Trait` is not implemented for `dyn Send`
@@ -10,6 +22,6 @@ help: the trait `Trait` is implemented for `u32`
LL | impl Trait for u32 {}
| ^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error
error: aborting due to 2 previous errors
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:15:32
--> $DIR/unsized_coercion3.rs:16:32
|
LL | let y: Box<dyn Send> = x;
| ^ doesn't have a size known at compile-time
+1
View File
@@ -9,6 +9,7 @@ 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
+4 -2
View File
@@ -7,6 +7,8 @@ use std::collections::HashMap;
fn main() {
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 `(&_, &_)`
//[current]~^ ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
//[current]~| ERROR expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
//[next]~^^^ ERROR: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
//[next]~| ERROR: expected `Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
}
@@ -5,9 +5,8 @@
fn main() {
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 a `FnMut(&{integer})` 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}`
//[next]~| ERROR expected a `FnMut(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item)` closure, found
//[next]~^^ ERROR: expected a `FnMut(&{integer})` closure, found
}
@@ -1,38 +1,31 @@
error[E0277]: expected a `FnMut(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
error[E0277]: expected a `FnMut(&{integer})` 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(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
| ---- ^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(&{integer})` 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 <std::ops::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 signature `for<'a> fn(&'a <std::ops::RangeInclusive<{integer}> as Iterator>::Item)`
= help: the trait `for<'a> FnMut(&'a {integer})` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}`
= note: expected a closure with signature `for<'a> fn(&'a {integer})`
found a closure with signature `fn(i32)`
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}`
error[E0277]: expected a `FnMut(&{integer})` 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
|
LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0);
| ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item)` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
| ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(&{integer})` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
| |
| required by a bound introduced by this call
|
= help: the trait `for<'a> FnMut(&'a <std::ops::RangeInclusive<{integer}> as Iterator>::Item)` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
= note: expected a closure with signature `for<'a> fn(&'a <std::ops::RangeInclusive<{integer}> as Iterator>::Item)`
= help: the trait `for<'a> FnMut(&'a {integer})` is not implemented for closure `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}`
= note: expected a closure with signature `for<'a> fn(&'a {integer})`
found a closure with signature `fn(&&&i32)`
note: required by a bound in `find`
--> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
error: aborting due to 3 previous errors
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0271, E0277.
For more information about an error, try `rustc --explain E0271`.
For more information about this error, try `rustc --explain E0277`.
@@ -5,9 +5,8 @@
fn main() {
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 a `FnMut(&{integer})` 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}`
//[next]~| ERROR expected a `FnMut(&<std::ops::RangeInclusive<{integer}> as Iterator>::Item)` closure, found
//[next]~^^ ERROR: expected a `FnMut(&{integer})` closure, found
}
@@ -1,4 +1,4 @@
// regression test for #73299.
// regression test for #74299.
#![feature(specialization)]
trait X {
@@ -18,7 +18,7 @@ trait Y {
impl Y for <() as X>::U {}
impl Y for <i32 as X>::U {}
//~^ ERROR conflicting implementations of trait `Y` for type `<() as X>::U`
//~^ ERROR conflicting implementations of trait `Y`
fn main() {
().f().g();
@@ -1,10 +1,10 @@
error[E0119]: conflicting implementations of trait `Y` for type `<() as X>::U`
error[E0119]: conflicting implementations of trait `Y`
--> $DIR/default-item-normalization-ambig-1.rs:20:1
|
LL | impl Y for <() as X>::U {}
| ----------------------- first implementation here
LL | impl Y for <i32 as X>::U {}
| ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<() as X>::U`
| ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
error: aborting due to 1 previous error
@@ -1,5 +1,5 @@
//@ compile-flags: -Znext-solver=globally
// Regression test for https://github.com/rust-lang/rust/issues/151327
// ICE regression test for https://github.com/rust-lang/rust/issues/151327
#![feature(min_specialization)]
@@ -9,15 +9,14 @@ trait Foo {
trait Baz {}
impl<'a, T> Foo for &'a T //~ ERROR not all trait items implemented, missing: `Item`
//~| ERROR the trait bound `&'a T: Foo` is not satisfied
impl<'a, T> Foo for &'a T
where
Self::Item: 'a, //~ ERROR the trait bound `&'a T: Foo` is not satisfied
Self::Item: 'a,
{
}
impl<'a, T> Foo for &T //~ ERROR not all trait items implemented, missing: `Item`
//~| ERROR cannot normalize `<&_ as Foo>::Item: '_`
impl<'a, T> Foo for &T
//~^ ERROR: conflicting implementations of trait `Foo` for type `&_`
where
Self::Item: Baz,
{
@@ -1,69 +1,17 @@
error[E0046]: not all trait items implemented, missing: `Item`
--> $DIR/next-solver-region-resolution.rs:12:1
|
LL | type Item;
| --------- `Item` from trait
...
LL | / impl<'a, T> Foo for &'a T
LL | |
LL | | where
LL | | Self::Item: 'a,
| |___________________^ missing `Item` in implementation
error[E0277]: the trait bound `&'a T: Foo` is not satisfied
--> $DIR/next-solver-region-resolution.rs:12:21
|
LL | impl<'a, T> Foo for &'a T
| ^^^^^ the trait `Foo` is not implemented for `&'a T`
|
help: the trait `Foo` is not implemented for `&'a _`
but it is implemented for `&_`
--> $DIR/next-solver-region-resolution.rs:12:1
error[E0119]: conflicting implementations of trait `Foo` for type `&_`
--> $DIR/next-solver-region-resolution.rs:18:1
|
LL | / impl<'a, T> Foo for &'a T
LL | |
LL | | where
LL | | Self::Item: 'a,
| |___________________^
error[E0277]: the trait bound `&'a T: Foo` is not satisfied
--> $DIR/next-solver-region-resolution.rs:15:17
|
LL | Self::Item: 'a,
| ^^ the trait `Foo` is not implemented for `&'a T`
|
help: the trait `Foo` is not implemented for `&'a _`
but it is implemented for `&_`
--> $DIR/next-solver-region-resolution.rs:12:1
|
LL | / impl<'a, T> Foo for &'a T
LL | |
LL | | where
LL | | Self::Item: 'a,
| |___________________^
error[E0046]: not all trait items implemented, missing: `Item`
--> $DIR/next-solver-region-resolution.rs:19:1
|
LL | type Item;
| --------- `Item` from trait
| |___________________- first implementation here
...
LL | / impl<'a, T> Foo for &T
LL | |
LL | | where
LL | | Self::Item: Baz,
| |____________________^ missing `Item` in implementation
| |____________________^ conflicting implementation for `&_`
error: cannot normalize `<&_ as Foo>::Item: '_`
--> $DIR/next-solver-region-resolution.rs:19:1
|
LL | / impl<'a, T> Foo for &T
LL | |
LL | | where
LL | | Self::Item: Baz,
| |____________________^
error: aborting due to 1 previous error
error: aborting due to 5 previous errors
Some errors have detailed explanations: E0046, E0277.
For more information about an error, try `rustc --explain E0046`.
For more information about this error, try `rustc --explain E0119`.
@@ -26,11 +26,9 @@ impl Foo for () {
fn main() {
let x = String::from("hello, world");
let _ = identity(<() as Foo>::copy_me(&x));
//~^ ERROR overflow evaluating whether `<() as Foo>::Item` is well-formed
//~| ERROR overflow evaluating whether `&<() as Foo>::Item` is well-formed
//~| ERROR overflow evaluating the requirement `String == <() as Foo>::Item`
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
//~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
//~^ ERROR: overflow evaluating the requirement `<() as Foo>::Item == String` [E0275]
//~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275]
//~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275]
//~| ERROR: overflow evaluating the requirement `<() as Foo>::Item == _` [E0275]
println!("{x}");
}
@@ -12,7 +12,7 @@ LL | trait Foo {
LL | type Item: Copy
| ^^^^ this trait's associated type doesn't have the requirement `String: Copy`
error[E0275]: overflow evaluating the requirement `String == <() as Foo>::Item`
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == String`
--> $DIR/alias-bound-unsound.rs:28:22
|
LL | let _ = identity(<() as Foo>::copy_me(&x));
@@ -25,25 +25,11 @@ LL | let _ = identity(<() as Foo>::copy_me(&x));
| ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
--> $DIR/alias-bound-unsound.rs:28:22
|
LL | let _ = identity(<() as Foo>::copy_me(&x));
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0275]: overflow evaluating whether `&<() as Foo>::Item` is well-formed
--> $DIR/alias-bound-unsound.rs:28:43
|
LL | let _ = identity(<() as Foo>::copy_me(&x));
| ^^
error[E0275]: overflow evaluating whether `<() as Foo>::Item` is well-formed
--> $DIR/alias-bound-unsound.rs:28:22
|
LL | let _ = identity(<() as Foo>::copy_me(&x));
| ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
--> $DIR/alias-bound-unsound.rs:28:22
|
@@ -52,6 +38,6 @@ LL | let _ = identity(<() as Foo>::copy_me(&x));
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 7 previous errors
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0275`.
@@ -1,10 +1,10 @@
error[E0119]: conflicting implementations of trait `Overlaps<Box<_>>` for type `<_ as TraitB>::Assoc`
error[E0119]: conflicting implementations of trait `Overlaps<Box<_>>`
--> $DIR/alias_eq_substs_eq_not_intercrate.rs:14:1
|
LL | impl<T: TraitB> Overlaps<Box<T>> for <T as TraitB>::Assoc {}
| --------------------------------------------------------- first implementation here
LL | impl<U: TraitB> Overlaps<U> for <U as TraitB>::Assoc {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `<_ as TraitB>::Assoc`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
|
= note: downstream crates may implement trait `TraitB` for type `std::boxed::Box<_>`
@@ -5,5 +5,6 @@ struct X<const FN: fn() = { || {} }>;
//~^ ERROR using function pointers as const generic parameters is forbidden
//~| ERROR using function pointers as const generic parameters is forbidden
//~| ERROR type annotations needed
//~| ERROR type annotations needed
fn main() {}
@@ -4,6 +4,18 @@ error[E0284]: type annotations needed: cannot satisfy `the constant `{ || {} }`
LL | struct X<const FN: fn() = { || {} }>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `the constant `{ || {} }` can be evaluated`
error[E0284]: type annotations needed
--> $DIR/const-region-infer-to-static-in-binder.rs:4:10
|
LL | struct X<const FN: fn() = { || {} }>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_`
|
note: required by a const generic parameter in `X`
--> $DIR/const-region-infer-to-static-in-binder.rs:4:10
|
LL | struct X<const FN: fn() = { || {} }>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `X`
error: using function pointers as const generic parameters is forbidden
--> $DIR/const-region-infer-to-static-in-binder.rs:4:20
|
@@ -21,6 +33,6 @@ LL | struct X<const FN: fn() = { || {} }>;
= note: the only supported types are integers, `bool`, and `char`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 3 previous errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0284`.
@@ -12,6 +12,5 @@ struct S {
fn main() {
let x: S = todo!();
let y: &() = x.f;
//~^ ERROR mismatched types
//~| ERROR the trait bound `(): Wf` is not satisfied
//~^ ERROR the trait bound `(): Wf` is not satisfied
}
@@ -10,17 +10,6 @@ help: this trait has no implementations, consider adding one
LL | trait Wf {
| ^^^^^^^^
error[E0308]: mismatched types
--> $DIR/non-wf-in-coerce-pointers.rs:14:18
|
LL | let y: &() = x.f;
| --- ^^^ types differ
| |
| expected due to this
|
= note: expected reference `&()`
found reference `&'static <() as Wf>::Assoc`
error[E0277]: the trait bound `(): Wf` is not satisfied
--> $DIR/non-wf-in-coerce-pointers.rs:14:18
|
@@ -33,7 +22,6 @@ help: this trait has no implementations, consider adding one
LL | trait Wf {
| ^^^^^^^^
error: aborting due to 3 previous errors
error: aborting due to 2 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`.
@@ -7,7 +7,8 @@ LL | struct LocalTy;
LL | impl Trait for <LocalTy as Overflow>::Assoc {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
|
= note: overflow evaluating the requirement `_ == <LocalTy as Overflow>::Assoc`
= note: overflow evaluating the requirement `<LocalTy as Overflow>::Assoc == _`
= note: overflow evaluating the requirement `<LocalTy as Overflow>::Assoc == _`
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`)
error: aborting due to 1 previous error
@@ -10,33 +10,13 @@ note: required by a bound in `transmute`
LL | fn transmute<L: Trait<R>, R>(r: L) -> <L::Proof as Trait<R>>::Proof { r }
| ^^^^^^^^ required by this bound in `transmute`
error[E0275]: overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == _`
error[E0275]: overflow evaluating the requirement `<Vec<u8> as Trait<String>>::Proof == _`
--> $DIR/item-bound-via-impl-where-clause.rs:31:21
|
LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0275]: overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == String`
--> $DIR/item-bound-via-impl-where-clause.rs:31:21
|
LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0275]: overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof: Sized`
--> $DIR/item-bound-via-impl-where-clause.rs:31:21
|
LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the return type of a function must have a statically known size
error[E0275]: overflow evaluating whether `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof` is well-formed
--> $DIR/item-bound-via-impl-where-clause.rs:31:21
|
LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0275]: overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == _`
error[E0275]: overflow evaluating the requirement `<Vec<u8> as Trait<String>>::Proof == _`
--> $DIR/item-bound-via-impl-where-clause.rs:31:21
|
LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
@@ -44,6 +24,6 @@ LL | let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 6 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0275`.
@@ -30,10 +30,7 @@ fn transmute<L: Trait<R>, R>(r: L) -> <L::Proof as Trait<R>>::Proof { r }
fn main() {
let s: String = transmute::<_, String>(vec![65_u8, 66, 67]);
//~^ ERROR overflow evaluating the requirement `Vec<u8>: Trait<String>`
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == _`
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == String`
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof: Sized`
//[next]~| ERROR overflow evaluating whether `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof` is well-formed
//[next]~| ERROR overflow evaluating the requirement `<<Vec<u8> as Trait<String>>::Proof as Trait<String>>::Proof == _`
//[next]~| ERROR: overflow evaluating the requirement `<Vec<u8> as Trait<String>>::Proof == _`
//[next]~| ERROR: overflow evaluating the requirement `<Vec<u8> as Trait<String>>::Proof == _`
println!("{}", s); // ABC
}
@@ -16,6 +16,6 @@ impl Trait for Overflow {
trait Overlap<T, WfHack> {}
impl<T: Trait, U: Copy> Overlap<T::Assoc<T>, U> for T {}
impl<U> Overlap<u32, U> for Overflow {}
//~^ ERROR conflicting implementations of trait `Overlap<<Overflow as Trait>::Assoc<Overflow>, _>` for type `Overflow`
//~^ ERROR: conflicting implementations of trait `Overlap<u32, _>` for type
fn main() {}
@@ -1,4 +1,4 @@
error[E0119]: conflicting implementations of trait `Overlap<<Overflow as Trait>::Assoc<Overflow>, _>` for type `Overflow`
error[E0119]: conflicting implementations of trait `Overlap<u32, _>` for type `Overflow`
--> $DIR/unproductive-in-coherence.rs:18:1
|
LL | impl<T: Trait, U: Copy> Overlap<T::Assoc<T>, U> for T {}
@@ -1,8 +1,8 @@
error[E0277]: the trait bound `T: Trait` is not satisfied
--> $DIR/projection-trait-ref.rs:8:12
--> $DIR/projection-trait-ref.rs:8:13
|
LL | let x: <T as Trait>::Assoc = ();
| ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
| ^ the trait `Trait` is not implemented for `T`
|
help: consider restricting type parameter `T` with trait `Trait`
|
@@ -10,10 +10,10 @@ LL | fn test_poly<T: Trait>() {
| +++++++
error[E0277]: the trait bound `i32: Trait` is not satisfied
--> $DIR/projection-trait-ref.rs:13:12
--> $DIR/projection-trait-ref.rs:13:13
|
LL | let x: <i32 as Trait>::Assoc = ();
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `i32`
| ^^^ the trait `Trait` is not implemented for `i32`
|
help: this trait has no implementations, consider adding one
--> $DIR/projection-trait-ref.rs:3:1
@@ -5,13 +5,15 @@ trait Trait<'a> {
}
fn foo(x: for<'a> fn(<() as Trait<'a>>::Assoc)) {
//~^ ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
//~| ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
//~| ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
//~^ ERROR: the trait bound `for<'a> (): Trait<'a>` is not satisfied
//~| ERROR: the trait bound `for<'a> (): Trait<'a>` is not satisfied
//~| ERROR: the trait bound `for<'a> (): Trait<'a>` is not satisfied
//~| ERROR: the trait bound `for<'a> (): Trait<'a>` is not satisfied
unsafe { std::mem::transmute::<_, ()>(x); }
//~^ ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
//~| ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
//~| ERROR the trait bound `for<'a> (): Trait<'a>` is not satisfied
//~^ ERROR: the trait bound `for<'a> (): Trait<'a>` is not satisfied
//~| ERROR: the trait bound `for<'a> (): Trait<'a>` is not satisfied
//~| ERROR: the trait bound `for<'a> (): Trait<'a>` is not satisfied
}
fn main() {}
@@ -10,6 +10,30 @@ help: this trait has no implementations, consider adding one
LL | trait Trait<'a> {
| ^^^^^^^^^^^^^^^
error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:7:11
|
LL | fn foo(x: for<'a> fn(<() as Trait<'a>>::Assoc)) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a>` is not implemented for `()`
|
help: this trait has no implementations, consider adding one
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
|
LL | trait Trait<'a> {
| ^^^^^^^^^^^^^^^
error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:12:43
|
LL | unsafe { std::mem::transmute::<_, ()>(x); }
| ^ the trait `for<'a> Trait<'a>` is not implemented for `()`
|
help: this trait has no implementations, consider adding one
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
|
LL | trait Trait<'a> {
| ^^^^^^^^^^^^^^^
error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:7:8
|
@@ -23,7 +47,7 @@ LL | trait Trait<'a> {
| ^^^^^^^^^^^^^^^
error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:11:14
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:12:14
|
LL | unsafe { std::mem::transmute::<_, ()>(x); }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait<'a>` is not implemented for `()`
@@ -35,7 +59,7 @@ LL | trait Trait<'a> {
| ^^^^^^^^^^^^^^^
error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:11:36
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:12:36
|
LL | unsafe { std::mem::transmute::<_, ()>(x); }
| ^ the trait `for<'a> Trait<'a>` is not implemented for `()`
@@ -46,18 +70,6 @@ help: this trait has no implementations, consider adding one
LL | trait Trait<'a> {
| ^^^^^^^^^^^^^^^
error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:11:43
|
LL | unsafe { std::mem::transmute::<_, ()>(x); }
| ^ the trait `for<'a> Trait<'a>` is not implemented for `()`
|
help: this trait has no implementations, consider adding one
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:3:1
|
LL | trait Trait<'a> {
| ^^^^^^^^^^^^^^^
error[E0277]: the trait bound `for<'a> (): Trait<'a>` is not satisfied
--> $DIR/dont-ice-on-bad-transmute-in-typeck.rs:7:1
|
@@ -70,6 +82,6 @@ help: this trait has no implementations, consider adding one
LL | trait Trait<'a> {
| ^^^^^^^^^^^^^^^
error: aborting due to 6 previous errors
error: aborting due to 7 previous errors
For more information about this error, try `rustc --explain E0277`.
@@ -11,6 +11,7 @@ fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
pub fn copy_any<T>(t: &T) -> T {
copy::<dyn Setup<From=T>>(t)
//~^ ERROR the trait bound `T: Copy` is not satisfied in `dyn Setup<From = T>`
//~| ERROR the trait bound `T: Copy` is not satisfied in `dyn Setup<From = T>`
//~| ERROR the trait bound `T: Copy` is not satisfied
// FIXME(-Znext-solver): These error messages are horrible and some of them
@@ -15,6 +15,18 @@ help: consider restricting type parameter `T` with trait `Copy`
LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T {
| +++++++++++++++++++
error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup<From = T>`
--> $DIR/dyn-incompatibility.rs:12:31
|
LL | copy::<dyn Setup<From=T>>(t)
| ^ within `dyn Setup<From = T>`, the trait `Copy` is not implemented for `T`
|
= note: required because it appears within the type `dyn Setup<From = T>`
help: consider restricting type parameter `T` with trait `Copy`
|
LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T {
| +++++++++++++++++++
error[E0277]: the trait bound `T: Copy` is not satisfied in `dyn Setup<From = T>`
--> $DIR/dyn-incompatibility.rs:12:5
|
@@ -27,6 +39,6 @@ help: consider restricting type parameter `T` with trait `Copy`
LL | pub fn copy_any<T: std::marker::Copy>(t: &T) -> T {
| +++++++++++++++++++
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0277`.
@@ -14,7 +14,7 @@ fn foo<T>()
where
T: for<'a> Proj<'a, Assoc = for<'b> fn(<T as Proj<'b>>::Assoc)>,
(): Trait<<T as Proj<'static>>::Assoc>
//~^ ERROR overflow evaluating the requirement `(): Trait<<T as Proj<'static>>::Assoc>` [E0275]
//~^ ERROR: overflow evaluating the requirement `(): Trait<<T as Proj<'static>>::Assoc>`
{
}
@@ -1,10 +1,10 @@
error[E0271]: type mismatch resolving `fn(&str) {f} == fn(&str)`
error[E0271]: type mismatch resolving `fn(&str) == fn(&str) {f}`
--> $DIR/lazy-nested-obligations-2.rs:20:21
|
LL | let _: V<i32> = V(f);
| ^^^^ types differ
error[E0271]: type mismatch resolving `fn(&str) {f} == fn(&str)`
error[E0271]: type mismatch resolving `fn(&str) == fn(&str) {f}`
--> $DIR/lazy-nested-obligations-2.rs:27:22
|
LL | let _: E3<i32> = E3::Var(f);
@@ -0,0 +1,22 @@
//@compile-flags: -Znext-solver
// Regression test for #151308
#![feature(lazy_type_alias)]
trait Trait {
type Associated;
}
trait Generic<T> {}
type TraitObject = dyn Generic<<i32 as Trait>::Associated>;
//~^ ERROR: the trait bound `i32: Trait` is not satisfied
struct Wrap(TraitObject);
//~^ ERROR: the trait bound `i32: Trait` is not satisfied
fn cast(x: *mut Wrap) {
x as *mut Wrap;
}
fn main() {}
@@ -0,0 +1,27 @@
error[E0277]: the trait bound `i32: Trait` is not satisfied
--> $DIR/dont-ice-on-normalization-failure.rs:12:32
|
LL | type TraitObject = dyn Generic<<i32 as Trait>::Associated>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `i32`
|
help: this trait has no implementations, consider adding one
--> $DIR/dont-ice-on-normalization-failure.rs:6:1
|
LL | trait Trait {
| ^^^^^^^^^^^
error[E0277]: the trait bound `i32: Trait` is not satisfied
--> $DIR/dont-ice-on-normalization-failure.rs:15:13
|
LL | struct Wrap(TraitObject);
| ^^^^^^^^^^^ the trait `Trait` is not implemented for `i32`
|
help: this trait has no implementations, consider adding one
--> $DIR/dont-ice-on-normalization-failure.rs:6:1
|
LL | trait Trait {
| ^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.
@@ -6,20 +6,44 @@ LL | | where
LL | | Self::Assoc: A<T>,
| |__________________________^
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>`
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc == _`
--> $DIR/normalize-param-env-2.rs:22:5
|
LL | / fn f()
LL | | where
LL | | Self::Assoc: A<T>,
| |__________________________^
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc == _`
--> $DIR/normalize-param-env-2.rs:24:22
|
LL | Self::Assoc: A<T>,
| ^^^^
error[E0283]: type annotations needed
--> $DIR/normalize-param-env-2.rs:24:22
|
note: the requirement `<() as A<T>>::Assoc: A<T>` appears on the `impl`'s associated function `f` but not on the corresponding trait's associated function
LL | Self::Assoc: A<T>,
| ^^^^ cannot infer type
|
note: multiple `impl`s or `where` clauses satisfying `_: A<T>` found
--> $DIR/normalize-param-env-2.rs:19:1
|
LL | impl<T> A<T> for () {
| ^^^^^^^^^^^^^^^^^^^
...
LL | Self::Assoc: A<T>,
| ^^^^
note: the requirement `_: A<T>` appears on the `impl`'s associated function `f` but not on the corresponding trait's associated function
--> $DIR/normalize-param-env-2.rs:12:8
|
LL | trait A<T> {
| - in this trait
...
LL | fn f()
| ^ this trait's associated function doesn't have the requirement `<() as A<T>>::Assoc: A<T>`
| ^ this trait's associated function doesn't have the requirement `_: A<T>`
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>`
--> $DIR/normalize-param-env-2.rs:24:22
@@ -39,12 +63,26 @@ error[E0275]: overflow evaluating the requirement `(): A<T>`
LL | <() as A<T>>::f();
| ^^
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>`
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc == _`
--> $DIR/normalize-param-env-2.rs:27:9
|
LL | <() as A<T>>::f();
| ^^^^^^^^^^^^^^^^^
error[E0283]: type annotations needed
--> $DIR/normalize-param-env-2.rs:27:9
|
LL | <() as A<T>>::f();
| ^^^^^^^^^^^^^^^^^ cannot infer type
|
note: multiple `impl`s or `where` clauses satisfying `_: A<T>` found
--> $DIR/normalize-param-env-2.rs:19:1
|
LL | impl<T> A<T> for () {
| ^^^^^^^^^^^^^^^^^^^
...
LL | Self::Assoc: A<T>,
| ^^^^
note: required by a bound in `A::f`
--> $DIR/normalize-param-env-2.rs:14:22
|
@@ -54,6 +92,7 @@ LL | where
LL | Self::Assoc: A<T>,
| ^^^^ required by this bound in `A::f`
error: aborting due to 6 previous errors
error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0275`.
Some errors have detailed explanations: E0275, E0283.
For more information about an error, try `rustc --explain E0275`.

Some files were not shown because too many files have changed in this diff Show More