mirror of
https://github.com/rust-lang/rust
synced 2024-10-14 20:46:49 +00:00
Auto merge of #113086 - lcnr:rust8, r=compiler-errors
implement deep normalization via the new solver together with #112869 this should remove all uses of the old solver with `-Ztrait-solver=next`. see https://hackmd.io/V0qsUB_fTxexfQO_pcOcrg for a description of this PR. Will move that doc to the `rustc-dev-guide` after merging this. r? `@compiler-errors`
This commit is contained in:
commit
737b461555
|
@ -4136,6 +4136,7 @@ dependencies = [
|
|||
name = "rustc_ty_utils"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_fluent_macro",
|
||||
|
|
|
@ -224,7 +224,8 @@ fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
|
|||
if check_opaque_for_cycles(tcx, item.owner_id.def_id, substs, span, &origin).is_err() {
|
||||
return;
|
||||
}
|
||||
check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin);
|
||||
|
||||
let _ = check_opaque_meets_bounds(tcx, item.owner_id.def_id, span, &origin);
|
||||
}
|
||||
|
||||
/// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
|
||||
|
@ -395,7 +396,7 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
def_id: LocalDefId,
|
||||
span: Span,
|
||||
origin: &hir::OpaqueTyOrigin,
|
||||
) {
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let defining_use_anchor = match *origin {
|
||||
hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
|
||||
hir::OpaqueTyOrigin::TyAlias { .. } => tcx.impl_trait_parent(def_id),
|
||||
|
@ -429,10 +430,10 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
Ok(()) => {}
|
||||
Err(ty_err) => {
|
||||
let ty_err = ty_err.to_string(tcx);
|
||||
tcx.sess.delay_span_bug(
|
||||
return Err(tcx.sess.delay_span_bug(
|
||||
span,
|
||||
format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -447,7 +448,8 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
// version.
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
let guar = infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
return Err(guar);
|
||||
}
|
||||
match origin {
|
||||
// Checked when type checking the function containing them.
|
||||
|
@ -461,14 +463,15 @@ fn check_opaque_meets_bounds<'tcx>(
|
|||
if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {}
|
||||
// Can have different predicates to their defining use
|
||||
hir::OpaqueTyOrigin::TyAlias { .. } => {
|
||||
let wf_tys = ocx.assumed_wf_types(param_env, span, def_id);
|
||||
let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, def_id)?;
|
||||
let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys);
|
||||
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
|
||||
let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env);
|
||||
ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env)?;
|
||||
}
|
||||
}
|
||||
// Clean up after ourselves
|
||||
let _ = infcx.take_opaque_types();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_enum_of_nonnullable_ptr<'tcx>(
|
||||
|
|
|
@ -2121,7 +2121,7 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||
_ => bug!(),
|
||||
}
|
||||
};
|
||||
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id);
|
||||
let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl_ty_def_id)?;
|
||||
|
||||
let normalize_cause = ObligationCause::new(
|
||||
impl_ty_span,
|
||||
|
|
|
@ -105,7 +105,12 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
|
|||
}
|
||||
f(&mut wfcx);
|
||||
|
||||
let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, span, body_def_id);
|
||||
let assumed_wf_types = match wfcx.ocx.assumed_wf_types_and_report_errors(param_env, body_def_id)
|
||||
{
|
||||
Ok(wf_types) => wf_types,
|
||||
Err(_guar) => return,
|
||||
};
|
||||
|
||||
let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types);
|
||||
|
||||
let errors = wfcx.select_all_or_error();
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
|
||||
use rustc_middle::ty::trait_def::TraitSpecializationKind;
|
||||
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{self, translate_substs_with_cause, wf, ObligationCtxt};
|
||||
|
@ -113,7 +113,7 @@ fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node
|
|||
let span = tcx.def_span(impl1_def_id);
|
||||
check_has_items(tcx, impl1_def_id, impl2_node, span);
|
||||
|
||||
if let Some((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) {
|
||||
if let Ok((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) {
|
||||
let impl2_def_id = impl2_node.def_id();
|
||||
debug!(?impl2_def_id, ?impl2_substs);
|
||||
|
||||
|
@ -171,16 +171,14 @@ fn get_impl_substs(
|
|||
tcx: TyCtxt<'_>,
|
||||
impl1_def_id: LocalDefId,
|
||||
impl2_node: Node,
|
||||
) -> Option<(SubstsRef<'_>, SubstsRef<'_>)> {
|
||||
) -> Result<(SubstsRef<'_>, SubstsRef<'_>), ErrorGuaranteed> {
|
||||
let infcx = &tcx.infer_ctxt().build();
|
||||
let ocx = ObligationCtxt::new(infcx);
|
||||
let param_env = tcx.param_env(impl1_def_id);
|
||||
|
||||
let assumed_wf_types =
|
||||
ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id);
|
||||
let impl1_span = tcx.def_span(impl1_def_id);
|
||||
let assumed_wf_types = ocx.assumed_wf_types_and_report_errors(param_env, impl1_def_id)?;
|
||||
|
||||
let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
|
||||
let impl1_span = tcx.def_span(impl1_def_id);
|
||||
let impl2_substs = translate_substs_with_cause(
|
||||
infcx,
|
||||
param_env,
|
||||
|
@ -198,8 +196,8 @@ fn get_impl_substs(
|
|||
|
||||
let errors = ocx.select_all_or_error();
|
||||
if !errors.is_empty() {
|
||||
ocx.infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
return None;
|
||||
let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(&errors);
|
||||
return Err(guar);
|
||||
}
|
||||
|
||||
let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_def_id, assumed_wf_types);
|
||||
|
@ -207,10 +205,10 @@ fn get_impl_substs(
|
|||
let _ = ocx.resolve_regions_and_report_errors(impl1_def_id, &outlives_env);
|
||||
let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
|
||||
let span = tcx.def_span(impl1_def_id);
|
||||
tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
|
||||
return None;
|
||||
let guar = tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
|
||||
return Err(guar);
|
||||
};
|
||||
Some((impl1_substs, impl2_substs))
|
||||
Ok((impl1_substs, impl2_substs))
|
||||
}
|
||||
|
||||
/// Returns a list of all of the unconstrained subst of the given impl.
|
||||
|
|
|
@ -89,7 +89,7 @@ pub fn check_call(
|
|||
_ => self.check_expr(callee_expr),
|
||||
};
|
||||
|
||||
let expr_ty = self.structurally_resolved_type(call_expr.span, original_callee_ty);
|
||||
let expr_ty = self.structurally_resolve_type(call_expr.span, original_callee_ty);
|
||||
|
||||
let mut autoderef = self.autoderef(callee_expr.span, expr_ty);
|
||||
let mut result = None;
|
||||
|
@ -138,7 +138,7 @@ fn try_overloaded_call_step(
|
|||
autoderef: &Autoderef<'a, 'tcx>,
|
||||
) -> Option<CallStep<'tcx>> {
|
||||
let adjusted_ty =
|
||||
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
|
||||
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
|
||||
|
||||
// If the callee is a bare function or a closure, then we're all set.
|
||||
match *adjusted_ty.kind() {
|
||||
|
|
|
@ -717,8 +717,8 @@ fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'tcx>) {
|
|||
|
||||
#[instrument(skip(fcx), level = "debug")]
|
||||
pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx>) {
|
||||
self.expr_ty = fcx.structurally_resolved_type(self.expr_span, self.expr_ty);
|
||||
self.cast_ty = fcx.structurally_resolved_type(self.cast_span, self.cast_ty);
|
||||
self.expr_ty = fcx.structurally_resolve_type(self.expr_span, self.expr_ty);
|
||||
self.cast_ty = fcx.structurally_resolve_type(self.cast_span, self.cast_ty);
|
||||
|
||||
debug!("check_cast({}, {:?} as {:?})", self.expr.hir_id, self.expr_ty, self.cast_ty);
|
||||
|
||||
|
|
|
@ -1005,7 +1005,7 @@ pub fn try_coerce(
|
|||
allow_two_phase: AllowTwoPhase,
|
||||
cause: Option<ObligationCause<'tcx>>,
|
||||
) -> RelateResult<'tcx, Ty<'tcx>> {
|
||||
let source = self.resolve_vars_with_obligations(expr_ty);
|
||||
let source = self.try_structurally_resolve_type(expr.span, expr_ty);
|
||||
debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
|
||||
|
||||
let cause =
|
||||
|
|
|
@ -380,7 +380,7 @@ fn check_expr_unary(
|
|||
let mut oprnd_t = self.check_expr_with_expectation(&oprnd, expected_inner);
|
||||
|
||||
if !oprnd_t.references_error() {
|
||||
oprnd_t = self.structurally_resolved_type(expr.span, oprnd_t);
|
||||
oprnd_t = self.structurally_resolve_type(expr.span, oprnd_t);
|
||||
match unop {
|
||||
hir::UnOp::Deref => {
|
||||
if let Some(ty) = self.lookup_derefing(expr, oprnd, oprnd_t) {
|
||||
|
@ -1266,13 +1266,13 @@ fn check_method_call(
|
|||
) -> Ty<'tcx> {
|
||||
let rcvr_t = self.check_expr(&rcvr);
|
||||
// no need to check for bot/err -- callee does that
|
||||
let rcvr_t = self.structurally_resolved_type(rcvr.span, rcvr_t);
|
||||
let rcvr_t = self.structurally_resolve_type(rcvr.span, rcvr_t);
|
||||
let span = segment.ident.span;
|
||||
|
||||
let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) {
|
||||
Ok(method) => {
|
||||
// We could add a "consider `foo::<params>`" suggestion here, but I wasn't able to
|
||||
// trigger this codepath causing `structurally_resolved_type` to emit an error.
|
||||
// trigger this codepath causing `structurally_resolve_type` to emit an error.
|
||||
|
||||
self.write_method_call(expr.hir_id, method);
|
||||
Ok(method)
|
||||
|
@ -2252,7 +2252,7 @@ fn check_field(
|
|||
) -> Ty<'tcx> {
|
||||
debug!("check_field(expr: {:?}, base: {:?}, field: {:?})", expr, base, field);
|
||||
let base_ty = self.check_expr(base);
|
||||
let base_ty = self.structurally_resolved_type(base.span, base_ty);
|
||||
let base_ty = self.structurally_resolve_type(base.span, base_ty);
|
||||
let mut private_candidate = None;
|
||||
let mut autoderef = self.autoderef(expr.span, base_ty);
|
||||
while let Some((deref_base_ty, _)) = autoderef.next() {
|
||||
|
@ -2300,7 +2300,7 @@ fn check_field(
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
|
||||
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
|
||||
|
||||
if let Some((adjustments, did)) = private_candidate {
|
||||
// (#90483) apply adjustments to avoid ExprUseVisitor from
|
||||
|
@ -2857,7 +2857,7 @@ fn check_expr_index(
|
|||
} else if idx_t.references_error() {
|
||||
idx_t
|
||||
} else {
|
||||
let base_t = self.structurally_resolved_type(base.span, base_t);
|
||||
let base_t = self.structurally_resolve_type(base.span, base_t);
|
||||
match self.lookup_indexing(expr, base, base_t, idx, idx_t) {
|
||||
Some((index_ty, element_ty)) => {
|
||||
// two-phase not needed because index_ty is never mutable
|
||||
|
@ -3084,7 +3084,7 @@ fn check_expr_asm_operand(&self, expr: &'tcx hir::Expr<'tcx>, is_input: bool) {
|
|||
// allows them to be inferred based on how they are used later in the
|
||||
// function.
|
||||
if is_input {
|
||||
let ty = self.structurally_resolved_type(expr.span, ty);
|
||||
let ty = self.structurally_resolve_type(expr.span, ty);
|
||||
match *ty.kind() {
|
||||
ty::FnDef(..) => {
|
||||
let fnptr_ty = self.tcx.mk_fn_ptr(ty.fn_sig(self.tcx));
|
||||
|
@ -3142,7 +3142,7 @@ fn check_offset_of(
|
|||
let mut current_container = container;
|
||||
|
||||
for &field in fields {
|
||||
let container = self.structurally_resolved_type(expr.span, current_container);
|
||||
let container = self.structurally_resolve_type(expr.span, current_container);
|
||||
|
||||
match container.kind() {
|
||||
ty::Adt(container_def, substs) if !container_def.is_enum() => {
|
||||
|
|
|
@ -83,6 +83,8 @@ pub(in super::super) fn warn_if_unreachable(&self, id: hir::HirId, span: Span, k
|
|||
/// version (resolve_vars_if_possible), this version will
|
||||
/// also select obligations if it seems useful, in an effort
|
||||
/// to get more type information.
|
||||
// FIXME(-Ztrait-solver=next): A lot of the calls to this method should
|
||||
// probably be `try_structurally_resolve_type` or `structurally_resolve_type` instead.
|
||||
pub(in super::super) fn resolve_vars_with_obligations(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
self.resolve_vars_with_obligations_and_mutate_fulfillment(ty, |_| {})
|
||||
}
|
||||
|
@ -1465,16 +1467,13 @@ fn add_required_obligations_with_code(
|
|||
}
|
||||
}
|
||||
|
||||
/// Resolves `typ` by a single level if `typ` is a type variable.
|
||||
/// Try to resolve `ty` to a structural type, normalizing aliases.
|
||||
///
|
||||
/// When the new solver is enabled, this will also attempt to normalize
|
||||
/// the type if it's a projection (note that it will not deeply normalize
|
||||
/// projections within the type, just the outermost layer of the type).
|
||||
///
|
||||
/// If no resolution is possible, then an error is reported.
|
||||
/// Numeric inference variables may be left unresolved.
|
||||
pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let mut ty = self.resolve_vars_with_obligations(ty);
|
||||
/// 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.
|
||||
pub fn try_structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let ty = self.resolve_vars_with_obligations(ty);
|
||||
|
||||
if self.next_trait_solver()
|
||||
&& let ty::Alias(ty::Projection, _) = ty.kind()
|
||||
|
@ -1483,15 +1482,27 @@ pub fn structurally_resolved_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
|||
.at(&self.misc(sp), self.param_env)
|
||||
.structurally_normalize(ty, &mut **self.fulfillment_cx.borrow_mut())
|
||||
{
|
||||
Ok(normalized_ty) => {
|
||||
ty = normalized_ty;
|
||||
},
|
||||
Ok(normalized_ty) => normalized_ty,
|
||||
Err(errors) => {
|
||||
let guar = self.err_ctxt().report_fulfillment_errors(&errors);
|
||||
return self.tcx.ty_error(guar);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ty
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolves `ty` by a single level if `ty` is a type variable.
|
||||
///
|
||||
/// When the new solver is enabled, this will also attempt to normalize
|
||||
/// the type if it's a projection (note that it will not deeply normalize
|
||||
/// projections within the type, just the outermost layer of the type).
|
||||
///
|
||||
/// If no resolution is possible, then an error is reported.
|
||||
/// Numeric inference variables may be left unresolved.
|
||||
pub fn structurally_resolve_type(&self, sp: Span, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let ty = self.try_structurally_resolve_type(sp, ty);
|
||||
|
||||
if !ty.is_ty_var() {
|
||||
ty
|
||||
|
|
|
@ -184,7 +184,7 @@ pub(in super::super) fn check_argument_types(
|
|||
|
||||
// If the arguments should be wrapped in a tuple (ex: closures), unwrap them here
|
||||
let (formal_input_tys, expected_input_tys) = if tuple_arguments == TupleArguments {
|
||||
let tuple_type = self.structurally_resolved_type(call_span, formal_input_tys[0]);
|
||||
let tuple_type = self.structurally_resolve_type(call_span, formal_input_tys[0]);
|
||||
match tuple_type.kind() {
|
||||
// We expected a tuple and got a tuple
|
||||
ty::Tuple(arg_types) => {
|
||||
|
@ -412,7 +412,7 @@ fn variadic_error<'tcx>(
|
|||
|
||||
// There are a few types which get autopromoted when passed via varargs
|
||||
// in C but we just error out instead and require explicit casts.
|
||||
let arg_ty = self.structurally_resolved_type(arg.span, arg_ty);
|
||||
let arg_ty = self.structurally_resolve_type(arg.span, arg_ty);
|
||||
match arg_ty.kind() {
|
||||
ty::Float(ty::FloatTy::F32) => {
|
||||
variadic_error(tcx.sess, arg.span, arg_ty, "c_double");
|
||||
|
|
|
@ -179,7 +179,7 @@ fn adjust_self_ty(
|
|||
assert_eq!(n, pick.autoderefs);
|
||||
|
||||
let mut adjustments = self.adjust_steps(&autoderef);
|
||||
let mut target = self.structurally_resolved_type(autoderef.span(), ty);
|
||||
let mut target = self.structurally_resolve_type(autoderef.span(), ty);
|
||||
|
||||
match pick.autoref_or_ptr_adjustment {
|
||||
Some(probe::AutorefOrPtrAdjustment::Autoref { mutbl, unsize }) => {
|
||||
|
|
|
@ -451,7 +451,7 @@ fn probe_op<OP, R>(
|
|||
} else {
|
||||
// Ended up encountering a type variable when doing autoderef,
|
||||
// but it may not be a type variable after processing obligations
|
||||
// in our local `FnCtxt`, so don't call `structurally_resolved_type`.
|
||||
// in our local `FnCtxt`, so don't call `structurally_resolve_type`.
|
||||
let ty = &bad_ty.ty;
|
||||
let ty = self
|
||||
.probe_instantiate_query_response(span, &orig_values, ty)
|
||||
|
|
|
@ -393,7 +393,7 @@ fn check_pat_lit(
|
|||
// They can denote both statically and dynamically-sized byte arrays.
|
||||
let mut pat_ty = ty;
|
||||
if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(..), .. }) = lt.kind {
|
||||
let expected = self.structurally_resolved_type(span, expected);
|
||||
let expected = self.structurally_resolve_type(span, expected);
|
||||
if let ty::Ref(_, inner_ty, _) = expected.kind()
|
||||
&& matches!(inner_ty.kind(), ty::Slice(_))
|
||||
{
|
||||
|
@ -501,7 +501,7 @@ fn check_pat_range(
|
|||
// This check is needed if both sides are inference variables.
|
||||
// We require types to be resolved here so that we emit inference failure
|
||||
// rather than "_ is not a char or numeric".
|
||||
let ty = self.structurally_resolved_type(span, expected);
|
||||
let ty = self.structurally_resolve_type(span, expected);
|
||||
if !(ty.is_numeric() || ty.is_char() || ty.references_error()) {
|
||||
if let Some((ref mut fail, _, _)) = lhs {
|
||||
*fail = true;
|
||||
|
@ -1289,7 +1289,7 @@ fn check_pat_tuple(
|
|||
let mut expected_len = elements.len();
|
||||
if ddpos.as_opt_usize().is_some() {
|
||||
// Require known type only when `..` is present.
|
||||
if let ty::Tuple(tys) = self.structurally_resolved_type(span, expected).kind() {
|
||||
if let ty::Tuple(tys) = self.structurally_resolve_type(span, expected).kind() {
|
||||
expected_len = tys.len();
|
||||
}
|
||||
}
|
||||
|
@ -2042,7 +2042,7 @@ fn check_pat_slice(
|
|||
def_bm: BindingMode,
|
||||
ti: TopInfo<'tcx>,
|
||||
) -> Ty<'tcx> {
|
||||
let expected = self.structurally_resolved_type(span, expected);
|
||||
let expected = self.structurally_resolve_type(span, expected);
|
||||
let (element_ty, opt_slice_ty, inferred) = match *expected.kind() {
|
||||
// An array, so we might have something like `let [a, b, c] = [0, 1, 2];`.
|
||||
ty::Array(element_ty, len) => {
|
||||
|
|
|
@ -107,7 +107,7 @@ fn try_index_step(
|
|||
index_expr: &hir::Expr<'_>,
|
||||
) -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)> {
|
||||
let adjusted_ty =
|
||||
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
|
||||
self.structurally_resolve_type(autoderef.span(), autoderef.final_ty(false));
|
||||
debug!(
|
||||
"try_index_step(expr={:?}, base_expr={:?}, adjusted_ty={:?}, \
|
||||
index_ty={:?})",
|
||||
|
|
|
@ -40,6 +40,7 @@ pub enum DefineOpaqueTypes {
|
|||
No,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct At<'a, 'tcx> {
|
||||
pub infcx: &'a InferCtxt<'tcx>,
|
||||
pub cause: &'a ObligationCause<'tcx>,
|
||||
|
|
|
@ -881,7 +881,7 @@
|
|||
///
|
||||
/// Note that we've liberated the late bound regions of function signatures, so
|
||||
/// this can not be used to check whether these types are well formed.
|
||||
query assumed_wf_types(key: DefId) -> &'tcx ty::List<Ty<'tcx>> {
|
||||
query assumed_wf_types(key: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
|
||||
desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) }
|
||||
}
|
||||
|
||||
|
|
|
@ -544,17 +544,8 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
|||
Ok(tcx.mk_fn_ptr(fty))
|
||||
}
|
||||
|
||||
// these two are already handled downstream in case of lazy normalization
|
||||
(&ty::Alias(ty::Projection, a_data), &ty::Alias(ty::Projection, b_data)) => {
|
||||
let projection_ty = relation.relate(a_data, b_data)?;
|
||||
Ok(tcx.mk_projection(projection_ty.def_id, projection_ty.substs))
|
||||
}
|
||||
|
||||
(&ty::Alias(ty::Inherent, a_data), &ty::Alias(ty::Inherent, b_data)) => {
|
||||
let alias_ty = relation.relate(a_data, b_data)?;
|
||||
Ok(tcx.mk_alias(ty::Inherent, tcx.mk_alias_ty(alias_ty.def_id, alias_ty.substs)))
|
||||
}
|
||||
|
||||
// The substs of opaque types may not all be invariant, so we have
|
||||
// to treat them separately from other aliases.
|
||||
(
|
||||
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: a_def_id, substs: a_substs, .. }),
|
||||
&ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, substs: b_substs, .. }),
|
||||
|
@ -571,6 +562,19 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
|
|||
Ok(tcx.mk_opaque(a_def_id, substs))
|
||||
}
|
||||
|
||||
// Alias tend to mostly already be handled downstream due to normalization.
|
||||
(&ty::Alias(a_kind, a_data), &ty::Alias(b_kind, b_data)) => {
|
||||
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This if can be removed
|
||||
// and the assert uncommented once the new desugaring is stable.
|
||||
if a_kind == b_kind {
|
||||
let alias_ty = relation.relate(a_data, b_data)?;
|
||||
// assert_eq!(a_kind, b_kind);
|
||||
Ok(tcx.mk_alias(a_kind, alias_ty))
|
||||
} else {
|
||||
Err(TypeError::Sorts(expected_found(relation, a, b)))
|
||||
}
|
||||
}
|
||||
|
||||
_ => Err(TypeError::Sorts(expected_found(relation, a, b))),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ pub fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentCtxt<'tcx> {
|
|||
}
|
||||
|
||||
impl<'tcx> TraitEngine<'tcx> for FulfillmentCtxt<'tcx> {
|
||||
#[instrument(level = "debug", skip(self, infcx))]
|
||||
fn register_predicate_obligation(
|
||||
&mut self,
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
mod eval_ctxt;
|
||||
mod fulfill;
|
||||
pub mod inspect;
|
||||
mod normalize;
|
||||
mod opaques;
|
||||
mod project_goals;
|
||||
mod search_graph;
|
||||
|
@ -34,6 +35,7 @@
|
|||
|
||||
pub use eval_ctxt::{EvalCtxt, InferCtxtEvalExt};
|
||||
pub use fulfill::FulfillmentCtxt;
|
||||
pub(crate) use normalize::deeply_normalize;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum SolverMode {
|
||||
|
|
220
compiler/rustc_trait_selection/src/solve/normalize.rs
Normal file
220
compiler/rustc_trait_selection/src/solve/normalize.rs
Normal file
|
@ -0,0 +1,220 @@
|
|||
use crate::traits::error_reporting::TypeErrCtxtExt;
|
||||
use crate::traits::query::evaluate_obligation::InferCtxtExt;
|
||||
use crate::traits::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_infer::infer::at::At;
|
||||
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc_infer::traits::TraitEngineExt;
|
||||
use rustc_infer::traits::{FulfillmentError, Obligation, TraitEngine};
|
||||
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind};
|
||||
use rustc_middle::traits::Reveal;
|
||||
use rustc_middle::ty::{self, AliasTy, Ty, TyCtxt, UniverseIndex};
|
||||
use rustc_middle::ty::{FallibleTypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
|
||||
|
||||
use super::FulfillmentCtxt;
|
||||
|
||||
/// Deeply normalize all aliases in `value`. This does not handle inference and expects
|
||||
/// its input to be already fully resolved.
|
||||
pub(crate) fn deeply_normalize<'tcx, T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
at: At<'_, 'tcx>,
|
||||
value: T,
|
||||
) -> Result<T, Vec<FulfillmentError<'tcx>>> {
|
||||
let fulfill_cx = FulfillmentCtxt::new(at.infcx);
|
||||
let mut folder = NormalizationFolder { at, fulfill_cx, depth: 0, universes: Vec::new() };
|
||||
|
||||
value.try_fold_with(&mut folder)
|
||||
}
|
||||
|
||||
struct NormalizationFolder<'me, 'tcx> {
|
||||
at: At<'me, 'tcx>,
|
||||
fulfill_cx: FulfillmentCtxt<'tcx>,
|
||||
depth: usize,
|
||||
universes: Vec<Option<UniverseIndex>>,
|
||||
}
|
||||
|
||||
impl<'tcx> NormalizationFolder<'_, 'tcx> {
|
||||
fn normalize_alias_ty(
|
||||
&mut self,
|
||||
alias: AliasTy<'tcx>,
|
||||
) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> {
|
||||
let infcx = self.at.infcx;
|
||||
let tcx = infcx.tcx;
|
||||
let recursion_limit = tcx.recursion_limit();
|
||||
if !recursion_limit.value_within_limit(self.depth) {
|
||||
self.at.infcx.err_ctxt().report_overflow_error(
|
||||
&alias.to_ty(tcx),
|
||||
self.at.cause.span,
|
||||
true,
|
||||
|_| {},
|
||||
);
|
||||
}
|
||||
|
||||
self.depth += 1;
|
||||
|
||||
let new_infer_ty = infcx.next_ty_var(TypeVariableOrigin {
|
||||
kind: TypeVariableOriginKind::NormalizeProjectionType,
|
||||
span: self.at.cause.span,
|
||||
});
|
||||
let obligation = Obligation::new(
|
||||
tcx,
|
||||
self.at.cause.clone(),
|
||||
self.at.param_env,
|
||||
ty::Binder::dummy(ty::ProjectionPredicate {
|
||||
projection_ty: alias,
|
||||
term: new_infer_ty.into(),
|
||||
}),
|
||||
);
|
||||
|
||||
// Do not emit an error if normalization is known to fail but instead
|
||||
// keep the projection unnormalized. This is the case for projections
|
||||
// with a `T: Trait` where-clause and opaque types outside of the defining
|
||||
// scope.
|
||||
let result = if infcx.predicate_may_hold(&obligation) {
|
||||
self.fulfill_cx.register_predicate_obligation(infcx, obligation);
|
||||
let errors = self.fulfill_cx.select_all_or_error(infcx);
|
||||
if !errors.is_empty() {
|
||||
return Err(errors);
|
||||
}
|
||||
let ty = infcx.resolve_vars_if_possible(new_infer_ty);
|
||||
ty.try_fold_with(self)?
|
||||
} else {
|
||||
alias.to_ty(tcx).try_super_fold_with(self)?
|
||||
};
|
||||
|
||||
self.depth -= 1;
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn normalize_unevaluated_const(
|
||||
&mut self,
|
||||
ty: Ty<'tcx>,
|
||||
uv: ty::UnevaluatedConst<'tcx>,
|
||||
) -> Result<ty::Const<'tcx>, Vec<FulfillmentError<'tcx>>> {
|
||||
let infcx = self.at.infcx;
|
||||
let tcx = infcx.tcx;
|
||||
let recursion_limit = tcx.recursion_limit();
|
||||
if !recursion_limit.value_within_limit(self.depth) {
|
||||
self.at.infcx.err_ctxt().report_overflow_error(
|
||||
&tcx.mk_const(uv, ty),
|
||||
self.at.cause.span,
|
||||
true,
|
||||
|_| {},
|
||||
);
|
||||
}
|
||||
|
||||
self.depth += 1;
|
||||
|
||||
let new_infer_ct = infcx.next_const_var(
|
||||
ty,
|
||||
ConstVariableOrigin {
|
||||
kind: ConstVariableOriginKind::MiscVariable,
|
||||
span: self.at.cause.span,
|
||||
},
|
||||
);
|
||||
let obligation = Obligation::new(
|
||||
tcx,
|
||||
self.at.cause.clone(),
|
||||
self.at.param_env,
|
||||
ty::Binder::dummy(ty::ProjectionPredicate {
|
||||
projection_ty: tcx.mk_alias_ty(uv.def, uv.substs),
|
||||
term: new_infer_ct.into(),
|
||||
}),
|
||||
);
|
||||
|
||||
let result = if infcx.predicate_may_hold(&obligation) {
|
||||
self.fulfill_cx.register_predicate_obligation(infcx, obligation);
|
||||
let errors = self.fulfill_cx.select_all_or_error(infcx);
|
||||
if !errors.is_empty() {
|
||||
return Err(errors);
|
||||
}
|
||||
let ct = infcx.resolve_vars_if_possible(new_infer_ct);
|
||||
ct.try_fold_with(self)?
|
||||
} else {
|
||||
tcx.mk_const(uv, ty).try_super_fold_with(self)?
|
||||
};
|
||||
|
||||
self.depth -= 1;
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for NormalizationFolder<'_, 'tcx> {
|
||||
type Error = Vec<FulfillmentError<'tcx>>;
|
||||
|
||||
fn interner(&self) -> TyCtxt<'tcx> {
|
||||
self.at.infcx.tcx
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
|
||||
let reveal = self.at.param_env.reveal();
|
||||
let infcx = self.at.infcx;
|
||||
if !needs_normalization(&ty, reveal) {
|
||||
return Ok(ty);
|
||||
}
|
||||
|
||||
// We don't normalize opaque types unless we have
|
||||
// `Reveal::All`, even if we're in the defining scope.
|
||||
let data = match *ty.kind() {
|
||||
ty::Alias(kind, alias_ty) if kind != ty::Opaque || reveal == Reveal::UserFacing => {
|
||||
alias_ty
|
||||
}
|
||||
_ => return ty.try_super_fold_with(self),
|
||||
};
|
||||
|
||||
if data.has_escaping_bound_vars() {
|
||||
let (data, mapped_regions, mapped_types, mapped_consts) =
|
||||
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
|
||||
let result = ensure_sufficient_stack(|| self.normalize_alias_ty(data))?;
|
||||
Ok(PlaceholderReplacer::replace_placeholders(
|
||||
infcx,
|
||||
mapped_regions,
|
||||
mapped_types,
|
||||
mapped_consts,
|
||||
&mut self.universes,
|
||||
result,
|
||||
))
|
||||
} else {
|
||||
ensure_sufficient_stack(|| self.normalize_alias_ty(data))
|
||||
}
|
||||
}
|
||||
|
||||
fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result<ty::Const<'tcx>, Self::Error> {
|
||||
let reveal = self.at.param_env.reveal();
|
||||
let infcx = self.at.infcx;
|
||||
if !needs_normalization(&ct, reveal) {
|
||||
return Ok(ct);
|
||||
}
|
||||
|
||||
let uv = match ct.kind() {
|
||||
ty::ConstKind::Unevaluated(ct) => ct,
|
||||
_ => return ct.try_super_fold_with(self),
|
||||
};
|
||||
|
||||
if uv.has_escaping_bound_vars() {
|
||||
let (uv, mapped_regions, mapped_types, mapped_consts) =
|
||||
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uv);
|
||||
let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct.ty(), uv))?;
|
||||
Ok(PlaceholderReplacer::replace_placeholders(
|
||||
infcx,
|
||||
mapped_regions,
|
||||
mapped_types,
|
||||
mapped_consts,
|
||||
&mut self.universes,
|
||||
result,
|
||||
))
|
||||
} else {
|
||||
ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct.ty(), uv))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -427,7 +427,11 @@ fn prove_negated_obligation<'tcx>(
|
|||
let body_def_id = body_def_id.as_local().unwrap_or(CRATE_DEF_ID);
|
||||
|
||||
let ocx = ObligationCtxt::new(&infcx);
|
||||
let wf_tys = ocx.assumed_wf_types(param_env, DUMMY_SP, body_def_id);
|
||||
let Ok(wf_tys) = ocx.assumed_wf_types(param_env, body_def_id)
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let outlives_env = OutlivesEnvironment::with_bounds(
|
||||
param_env,
|
||||
infcx.implied_bounds_tys(param_env, body_def_id, wf_tys),
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
use super::TraitEngine;
|
||||
use super::{ChalkFulfillmentContext, FulfillmentContext};
|
||||
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
|
||||
use crate::traits::error_reporting::TypeErrCtxtExt;
|
||||
use crate::traits::NormalizeExt;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
|
@ -24,7 +25,6 @@
|
|||
use rustc_middle::ty::TypeFoldable;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_session::config::TraitSolver;
|
||||
use rustc_span::Span;
|
||||
|
||||
pub trait TraitEngineExt<'tcx> {
|
||||
fn new(infcx: &InferCtxt<'tcx>) -> Box<Self>;
|
||||
|
@ -198,17 +198,24 @@ pub fn resolve_regions_and_report_errors(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn assumed_wf_types_and_report_errors(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
def_id: LocalDefId,
|
||||
) -> Result<FxIndexSet<Ty<'tcx>>, ErrorGuaranteed> {
|
||||
self.assumed_wf_types(param_env, def_id)
|
||||
.map_err(|errors| self.infcx.err_ctxt().report_fulfillment_errors(&errors))
|
||||
}
|
||||
|
||||
pub fn assumed_wf_types(
|
||||
&self,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
span: Span,
|
||||
def_id: LocalDefId,
|
||||
) -> FxIndexSet<Ty<'tcx>> {
|
||||
) -> Result<FxIndexSet<Ty<'tcx>>, Vec<FulfillmentError<'tcx>>> {
|
||||
let tcx = self.infcx.tcx;
|
||||
let assumed_wf_types = tcx.assumed_wf_types(def_id);
|
||||
let mut implied_bounds = FxIndexSet::default();
|
||||
let cause = ObligationCause::misc(span, def_id);
|
||||
for ty in assumed_wf_types {
|
||||
let mut errors = Vec::new();
|
||||
for &(ty, span) in tcx.assumed_wf_types(def_id) {
|
||||
// FIXME(@lcnr): rustc currently does not check wf for types
|
||||
// pre-normalization, meaning that implied bounds are sometimes
|
||||
// incorrect. See #100910 for more details.
|
||||
|
@ -221,10 +228,19 @@ pub fn assumed_wf_types(
|
|||
// sound and then uncomment this line again.
|
||||
|
||||
// implied_bounds.insert(ty);
|
||||
let normalized = self.normalize(&cause, param_env, ty);
|
||||
implied_bounds.insert(normalized);
|
||||
let cause = ObligationCause::misc(span, def_id);
|
||||
match self
|
||||
.infcx
|
||||
.at(&cause, param_env)
|
||||
.deeply_normalize(ty, &mut **self.engine.borrow_mut())
|
||||
{
|
||||
// Insert well-formed types, ignoring duplicates.
|
||||
Ok(normalized) => drop(implied_bounds.insert(normalized)),
|
||||
Err(normalization_errors) => errors.extend(normalization_errors),
|
||||
};
|
||||
}
|
||||
implied_bounds
|
||||
|
||||
if errors.is_empty() { Ok(implied_bounds) } else { Err(errors) }
|
||||
}
|
||||
|
||||
pub fn make_canonicalized_query_response<T>(
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
use std::fmt::Debug;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
pub(crate) use self::project::{needs_normalization, BoundVarReplacer, PlaceholderReplacer};
|
||||
|
||||
pub use self::FulfillmentErrorCode::*;
|
||||
pub use self::ImplSource::*;
|
||||
pub use self::ObligationCauseCode::*;
|
||||
|
@ -407,7 +409,12 @@ fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
|||
)
|
||||
}
|
||||
|
||||
/// Normalize a type and process all resulting obligations, returning any errors
|
||||
/// Normalize a type and process all resulting obligations, returning any errors.
|
||||
///
|
||||
/// FIXME(-Ztrait-solver=next): This should be replaced by `At::deeply_normalize`
|
||||
/// which has the same behavior with the new solver. Because using a separate
|
||||
/// fulfillment context worsens caching in the old solver, `At::deeply_normalize`
|
||||
/// is still lazy with the old solver as it otherwise negatively impacts perf.
|
||||
#[instrument(skip_all)]
|
||||
pub fn fully_normalize<'tcx, T>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
|
|
|
@ -28,7 +28,9 @@
|
|||
use rustc_infer::infer::at::At;
|
||||
use rustc_infer::infer::resolve::OpportunisticRegionResolver;
|
||||
use rustc_infer::infer::DefineOpaqueTypes;
|
||||
use rustc_infer::traits::FulfillmentError;
|
||||
use rustc_infer::traits::ObligationCauseCode;
|
||||
use rustc_infer::traits::TraitEngine;
|
||||
use rustc_middle::traits::select::OverflowError;
|
||||
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt};
|
||||
|
@ -53,14 +55,55 @@ pub trait NormalizeExt<'tcx> {
|
|||
/// This normalization should be used when the type contains inference variables or the
|
||||
/// projection may be fallible.
|
||||
fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> InferOk<'tcx, T>;
|
||||
|
||||
/// Deeply normalizes `value`, replacing all aliases which can by normalized in
|
||||
/// the current environment. In the new solver this errors in case normalization
|
||||
/// fails or is ambiguous. This only normalizes opaque types with `Reveal::All`.
|
||||
///
|
||||
/// In the old solver this simply uses `normalizes` and adds the nested obligations
|
||||
/// to the `fulfill_cx`. This is necessary as we otherwise end up recomputing the
|
||||
/// same goals in both a temporary and the shared context which negatively impacts
|
||||
/// performance as these don't share caching.
|
||||
///
|
||||
/// FIXME(-Ztrait-solver=next): This has the same behavior as `traits::fully_normalize`
|
||||
/// in the new solver, but because of performance reasons, we currently reuse an
|
||||
/// existing fulfillment context in the old solver. Once we also eagerly prove goals with
|
||||
/// the old solver or have removed the old solver, remove `traits::fully_normalize` and
|
||||
/// rename this function to `At::fully_normalize`.
|
||||
fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
value: T,
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
||||
) -> Result<T, Vec<FulfillmentError<'tcx>>>;
|
||||
}
|
||||
|
||||
impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> {
|
||||
fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> InferOk<'tcx, T> {
|
||||
let mut selcx = SelectionContext::new(self.infcx);
|
||||
let Normalized { value, obligations } =
|
||||
normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value);
|
||||
InferOk { value, obligations }
|
||||
if self.infcx.next_trait_solver() {
|
||||
InferOk { value, obligations: Vec::new() }
|
||||
} else {
|
||||
let mut selcx = SelectionContext::new(self.infcx);
|
||||
let Normalized { value, obligations } =
|
||||
normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value);
|
||||
InferOk { value, obligations }
|
||||
}
|
||||
}
|
||||
|
||||
fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
value: T,
|
||||
fulfill_cx: &mut dyn TraitEngine<'tcx>,
|
||||
) -> Result<T, Vec<FulfillmentError<'tcx>>> {
|
||||
if self.infcx.next_trait_solver() {
|
||||
crate::solve::deeply_normalize(self, value)
|
||||
} else {
|
||||
let value = self
|
||||
.normalize(value)
|
||||
.into_value_registering_obligations(self.infcx, &mut *fulfill_cx);
|
||||
let errors = fulfill_cx.select_where_possible(self.infcx);
|
||||
let value = self.infcx.resolve_vars_if_possible(value);
|
||||
if errors.is_empty() { Ok(value) } else { Err(errors) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ pub trait QueryNormalizeExt<'tcx> {
|
|||
///
|
||||
/// After codegen, when lifetimes do not matter, it is preferable to instead
|
||||
/// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure.
|
||||
fn query_normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
|
||||
fn query_normalize<T>(self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> {
|
|||
/// normalizing, but for now should be used only when we actually
|
||||
/// know that normalization will succeed, since error reporting
|
||||
/// and other details are still "under development".
|
||||
fn query_normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
|
||||
fn query_normalize<T>(self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
|
||||
where
|
||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
||||
{
|
||||
|
@ -60,6 +60,16 @@ fn query_normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution
|
|||
self.param_env,
|
||||
self.cause,
|
||||
);
|
||||
|
||||
if self.infcx.next_trait_solver() {
|
||||
match crate::solve::deeply_normalize(self, value) {
|
||||
Ok(value) => return Ok(Normalized { value, obligations: vec![] }),
|
||||
Err(_errors) => {
|
||||
return Err(NoSolution);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !needs_normalization(&value, self.param_env.reveal()) {
|
||||
return Ok(Normalized { value, obligations: vec![] });
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
tracing = "0.1"
|
||||
itertools = "0.10.1"
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_errors = { path = "../rustc_errors" }
|
||||
|
|
|
@ -1,45 +1,56 @@
|
|||
use rustc_hir::{def::DefKind, def_id::DefId};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use std::iter;
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
*providers = Providers { assumed_wf_types, ..*providers };
|
||||
}
|
||||
|
||||
fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
|
||||
fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Fn => {
|
||||
let sig = tcx.fn_sig(def_id).subst_identity();
|
||||
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
|
||||
liberated_sig.inputs_and_output
|
||||
let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
|
||||
tcx.arena.alloc_from_iter(itertools::zip_eq(
|
||||
liberated_sig.inputs_and_output,
|
||||
fn_sig_spans(tcx, def_id),
|
||||
))
|
||||
}
|
||||
DefKind::AssocFn => {
|
||||
let sig = tcx.fn_sig(def_id).subst_identity();
|
||||
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
|
||||
let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
|
||||
let mut assumed_wf_types: Vec<_> =
|
||||
tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into();
|
||||
assumed_wf_types.extend(liberated_sig.inputs_and_output);
|
||||
tcx.mk_type_list(&assumed_wf_types)
|
||||
tcx.assumed_wf_types(tcx.local_parent(def_id)).into();
|
||||
assumed_wf_types.extend(itertools::zip_eq(
|
||||
liberated_sig.inputs_and_output,
|
||||
fn_sig_spans(tcx, def_id),
|
||||
));
|
||||
tcx.arena.alloc_slice(&assumed_wf_types)
|
||||
}
|
||||
DefKind::Impl { .. } => {
|
||||
match tcx.impl_trait_ref(def_id) {
|
||||
Some(trait_ref) => {
|
||||
let types: Vec<_> = trait_ref.skip_binder().substs.types().collect();
|
||||
tcx.mk_type_list(&types)
|
||||
}
|
||||
// Only the impl self type
|
||||
None => tcx.mk_type_list(&[tcx.type_of(def_id).subst_identity()]),
|
||||
}
|
||||
// Trait arguments and the self type for trait impls or only the self type for
|
||||
// inherent impls.
|
||||
let tys = match tcx.impl_trait_ref(def_id) {
|
||||
Some(trait_ref) => trait_ref.skip_binder().substs.types().collect(),
|
||||
None => vec![tcx.type_of(def_id).subst_identity()],
|
||||
};
|
||||
|
||||
let mut impl_spans = impl_spans(tcx, def_id);
|
||||
tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap())))
|
||||
}
|
||||
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
|
||||
DefKind::OpaqueTy => match tcx.def_kind(tcx.parent(def_id)) {
|
||||
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
|
||||
DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) {
|
||||
DefKind::TyAlias => ty::List::empty(),
|
||||
DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
|
||||
DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
|
||||
// Nested opaque types only occur in associated types:
|
||||
// ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
|
||||
// assumed_wf_types should include those of `Opaque<T>`, `Opaque<T>` itself
|
||||
// and `&'static T`.
|
||||
DefKind::OpaqueTy => bug!("unimplemented implied bounds for neseted opaque types"),
|
||||
DefKind::OpaqueTy => bug!("unimplemented implied bounds for nested opaque types"),
|
||||
def_kind @ _ => {
|
||||
bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}")
|
||||
}
|
||||
|
@ -72,3 +83,28 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
|
|||
| DefKind::Generator => ty::List::empty(),
|
||||
}
|
||||
}
|
||||
|
||||
fn fn_sig_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ {
|
||||
let node = tcx.hir().get(tcx.local_def_id_to_hir_id(def_id));
|
||||
if let Some(decl) = node.fn_decl() {
|
||||
decl.inputs.iter().map(|ty| ty.span).chain(iter::once(decl.output.span()))
|
||||
} else {
|
||||
bug!("unexpected item for fn {def_id:?}: {node:?}")
|
||||
}
|
||||
}
|
||||
|
||||
fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ {
|
||||
let item = tcx.hir().expect_item(def_id);
|
||||
if let hir::ItemKind::Impl(impl_) = item.kind {
|
||||
let trait_args = impl_
|
||||
.of_trait
|
||||
.into_iter()
|
||||
.flat_map(|trait_ref| trait_ref.path.segments.last().unwrap().args().args)
|
||||
.map(|arg| arg.span());
|
||||
let dummy_spans_for_default_args =
|
||||
impl_.of_trait.into_iter().flat_map(|trait_ref| iter::repeat(trait_ref.path.span));
|
||||
iter::once(impl_.self_ty.span).chain(trait_args).chain(dummy_spans_for_default_args)
|
||||
} else {
|
||||
bug!("unexpected item for impl {def_id:?}: {item:?}")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-109789.rs:18:1
|
||||
--> $DIR/issue-109789.rs:18:11
|
||||
|
|
||||
LL | fn bar(_: Foo<for<'a> fn(&'a ())>::Assoc) {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
||||
|
|
||||
= note: expected struct `Foo<fn(&'static ())>`
|
||||
found struct `Foo<for<'a> fn(&'a ())>`
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/param-env-infer.rs:5:12
|
||||
|
|
||||
LL | #![feature(dyn_star, pointer_like_trait)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/param-env-infer.rs:13:10
|
||||
|
|
||||
LL | t as _
|
||||
| ^ cannot infer type
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
|
@ -1,38 +0,0 @@
|
|||
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
--> $DIR/param-env-infer.rs:5:12
|
||||
|
|
||||
LL | #![feature(dyn_star, pointer_like_trait)]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0391]: cycle detected when computing type of `make_dyn_star::{opaque#0}`
|
||||
--> $DIR/param-env-infer.rs:11:60
|
||||
|
|
||||
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires type-checking `make_dyn_star`...
|
||||
--> $DIR/param-env-infer.rs:11:1
|
||||
|
|
||||
LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which requires computing layout of `make_dyn_star::{opaque#0}`...
|
||||
= note: ...which requires normalizing `make_dyn_star::{opaque#0}`...
|
||||
= note: ...which again requires computing type of `make_dyn_star::{opaque#0}`, completing the cycle
|
||||
note: cycle used when checking item types in top-level module
|
||||
--> $DIR/param-env-infer.rs:5:1
|
||||
|
|
||||
LL | / #![feature(dyn_star, pointer_like_trait)]
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | use std::fmt::Debug;
|
||||
... |
|
||||
LL | |
|
||||
LL | | fn main() {}
|
||||
| |____________^
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
9
tests/ui/dyn-star/param-env-region-infer.current.stderr
Normal file
9
tests/ui/dyn-star/param-env-region-infer.current.stderr
Normal file
|
@ -0,0 +1,9 @@
|
|||
error[E0282]: type annotations needed
|
||||
--> $DIR/param-env-region-infer.rs:16:10
|
||||
|
|
||||
LL | t as _
|
||||
| ^ cannot infer type
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0282`.
|
|
@ -1,15 +1,18 @@
|
|||
// revisions: current next
|
||||
//[next] compile-flags: -Ztrait-solver=next
|
||||
//[next] check-pass
|
||||
// incremental
|
||||
|
||||
// checks that we don't ICE if there are region inference variables in the environment
|
||||
// when computing `PointerLike` builtin candidates.
|
||||
|
||||
#![feature(dyn_star, pointer_like_trait)]
|
||||
//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::marker::PointerLike;
|
||||
|
||||
fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
|
||||
//[next]~^ ERROR cycle detected when computing type of `make_dyn_star::{opaque#0}`
|
||||
t as _
|
||||
//[current]~^ ERROR type annotations needed
|
||||
}
|
|
@ -20,6 +20,53 @@ error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is
|
|||
LL | for item in *things { *item = 0 }
|
||||
| ^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error[E0277]: `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not an iterator
|
||||
--> $DIR/issue-20605.rs:5:17
|
||||
|
|
||||
LL | for item in *things { *item = 0 }
|
||||
| ^^^^^^^ `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not an iterator
|
||||
|
|
||||
= help: the trait `Iterator` is not implemented for `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter`
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
error: the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
|
||||
--> $DIR/issue-20605.rs:5:17
|
||||
|
|
||||
LL | for item in *things { *item = 0 }
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0614]: type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced
|
||||
--> $DIR/issue-20605.rs:5:27
|
||||
|
|
||||
LL | for item in *things { *item = 0 }
|
||||
| ^^^^^
|
||||
|
||||
error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
|
||||
--> $DIR/issue-20605.rs:5:9
|
||||
|
|
||||
LL | for item in *things { *item = 0 }
|
||||
| ^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item`
|
||||
= note: all local variables must have a statically known size
|
||||
= help: unsized locals are gated as an unstable feature
|
||||
|
||||
error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
|
||||
--> $DIR/issue-20605.rs:5:17
|
||||
|
|
||||
LL | for item in *things { *item = 0 }
|
||||
| ^^^^^^^
|
||||
|
||||
error[E0277]: the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
|
||||
--> $DIR/issue-20605.rs:5:5
|
||||
|
|
||||
LL | for item in *things { *item = 0 }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item`
|
||||
note: required by a bound in `None`
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0614.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -3,9 +3,18 @@
|
|||
|
||||
fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) {
|
||||
for item in *things { *item = 0 }
|
||||
//~^ ERROR the size for values of type
|
||||
//[next]~^^ ERROR the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
|
||||
//[next]~| ERROR the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
|
||||
//[current]~^ ERROR the size for values of type
|
||||
//[next]~^^ ERROR the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
|
||||
//[next]~| ERROR the size for values of type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` cannot be known at compilation time
|
||||
//[next]~| ERROR the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
|
||||
//[next]~| ERROR `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not an iterator
|
||||
//[next]~| ERROR the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
|
||||
//[next]~| ERROR the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
|
||||
//[next]~| ERROR the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
|
||||
//[next]~| ERROR the size for values of type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be known at compilation time
|
||||
//[next]~| ERROR type `<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item` cannot be dereferenced
|
||||
// FIXME(-Ztrait-solver=next): these error messages are horrible and have to be
|
||||
// improved before we stabilize the new solver.
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -7,7 +7,6 @@ trait Trait2<'a> {
|
|||
|
||||
fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
|
||||
//~^ ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied
|
||||
//~| ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied
|
||||
let _e: (usize, usize) = unsafe{mem::transmute(param)};
|
||||
}
|
||||
|
||||
|
|
|
@ -4,16 +4,6 @@ error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
|
|||
LL | fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
|
||||
|
||||
error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
|
||||
--> $DIR/issue-35570.rs:8:1
|
||||
|
|
||||
LL | / fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | let _e: (usize, usize) = unsafe{mem::transmute(param)};
|
||||
LL | | }
|
||||
| |_^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -20,7 +20,6 @@ trait Trait2<'a, 'b> {
|
|||
// do not infer that.
|
||||
fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
|
||||
//~^ ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
|
||||
//~| ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -9,21 +9,6 @@ help: consider restricting type parameter `T`
|
|||
LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
|
||||
| ++++++++++++++++++++++++
|
||||
|
||||
error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
|
||||
--> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1
|
||||
|
|
||||
LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | {
|
||||
LL | | }
|
||||
| |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
|
||||
|
|
||||
help: consider restricting type parameter `T`
|
||||
|
|
||||
LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
|
||||
| ++++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -21,9 +21,7 @@ impl Foo for () {
|
|||
fn main() {
|
||||
let x = String::from("hello, world");
|
||||
drop(<() as Foo>::copy_me(&x));
|
||||
//~^ ERROR `<() as Foo>::Item: Copy` is not satisfied
|
||||
//~| ERROR `<() as Foo>::Item` is not well-formed
|
||||
//~| ERROR `<() as Foo>::Item` is not well-formed
|
||||
//~^ ERROR the type `&<() as Foo>::Item` is not well-formed
|
||||
//~| ERROR `<() as Foo>::Item` is not well-formed
|
||||
println!("{x}");
|
||||
}
|
||||
|
|
|
@ -1,17 +1,8 @@
|
|||
error[E0277]: the trait bound `<() as Foo>::Item: Copy` is not satisfied
|
||||
--> $DIR/alias-bound-unsound.rs:23:10
|
||||
error: the type `&<() as Foo>::Item` is not well-formed
|
||||
--> $DIR/alias-bound-unsound.rs:23:31
|
||||
|
|
||||
LL | drop(<() as Foo>::copy_me(&x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `<() as Foo>::Item`
|
||||
|
|
||||
note: required by a bound in `Foo::Item`
|
||||
--> $DIR/alias-bound-unsound.rs:10:30
|
||||
|
|
||||
LL | type Item: Copy
|
||||
| ---- required by a bound in this associated type
|
||||
LL | where
|
||||
LL | <Self as Foo>::Item: Copy;
|
||||
| ^^^^ required by this bound in `Foo::Item`
|
||||
| ^^
|
||||
|
||||
error: the type `<() as Foo>::Item` is not well-formed
|
||||
--> $DIR/alias-bound-unsound.rs:23:10
|
||||
|
@ -19,18 +10,5 @@ error: the type `<() as Foo>::Item` is not well-formed
|
|||
LL | drop(<() as Foo>::copy_me(&x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: the type `<() as Foo>::Item` is not well-formed
|
||||
--> $DIR/alias-bound-unsound.rs:23:5
|
||||
|
|
||||
LL | drop(<() as Foo>::copy_me(&x));
|
||||
| ^^^^
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
error: the type `<() as Foo>::Item` is not well-formed
|
||||
--> $DIR/alias-bound-unsound.rs:23:10
|
||||
|
|
||||
LL | drop(<() as Foo>::copy_me(&x));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -1,22 +1,17 @@
|
|||
// compile-flags: -Ztrait-solver=next
|
||||
|
||||
// check-pass
|
||||
// (should not pass, should be turned into a coherence-only test)
|
||||
|
||||
// check that a `alias-eq(<?0 as TraitB>::Assoc, <T as TraitB>::Assoc)` goal fails.
|
||||
|
||||
// FIXME(deferred_projection_equality): add a test that this is true during coherence
|
||||
// check that a `alias-eq(<?a as TraitB>::Assoc, <?b as TraitB>::Assoc)` goal fails
|
||||
// during coherence. We must not incorrectly constrain `?a` and `?b` to be
|
||||
// equal.
|
||||
|
||||
trait TraitB {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
fn needs_a<T: TraitB>() -> T::Assoc {
|
||||
unimplemented!()
|
||||
}
|
||||
trait Overlaps<T> {}
|
||||
|
||||
fn bar<T: TraitB>() {
|
||||
let _: <_ as TraitB>::Assoc = needs_a::<T>();
|
||||
}
|
||||
impl<T: TraitB> Overlaps<Box<T>> for <T as TraitB>::Assoc {}
|
||||
impl<U: TraitB> Overlaps<U> for <U as TraitB>::Assoc {}
|
||||
//~^ ERROR conflicting implementations of trait
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
error[E0119]: conflicting implementations of trait `Overlaps<Box<_>>` for type `<_ as TraitB>::Assoc`
|
||||
--> $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`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0119`.
|
|
@ -1,8 +1,8 @@
|
|||
error[E0271]: expected `[async block@$DIR/async.rs:12:17: 12:25]` to be a future that resolves to `i32`, but it resolves to `()`
|
||||
error[E0271]: type mismatch resolving `<[async block@$DIR/async.rs:12:17: 12:25] as Future>::Output == i32`
|
||||
--> $DIR/async.rs:12:17
|
||||
|
|
||||
LL | needs_async(async {});
|
||||
| ----------- ^^^^^^^^ expected `i32`, found `()`
|
||||
| ----------- ^^^^^^^^ types differ
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
|
|
|
@ -10,7 +10,7 @@ fn needs_async(_: impl Future<Output = i32>) {}
|
|||
#[cfg(fail)]
|
||||
fn main() {
|
||||
needs_async(async {});
|
||||
//[fail]~^ ERROR to be a future that resolves to `i32`, but it resolves to `()`
|
||||
//[fail]~^ ERROR type mismatch
|
||||
}
|
||||
|
||||
#[cfg(pass)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// compile-flags: -Ztrait-solver=next
|
||||
// check-pass
|
||||
// known-bug: #112825
|
||||
|
||||
// Makes sure we don't prepopulate the MIR typeck of `define`
|
||||
// with `Foo<T, U> = T`, but instead, `Foo<B, A> = B`, so that
|
||||
|
|
99
tests/ui/traits/new-solver/dont-remap-tait-substs.stderr
Normal file
99
tests/ui/traits/new-solver/dont-remap-tait-substs.stderr
Normal file
|
@ -0,0 +1,99 @@
|
|||
error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
|
||||
--> $DIR/dont-remap-tait-substs.rs:10:24
|
||||
|
|
||||
LL | type Foo<T: Send, U> = impl NeedsSend<T>;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires borrow-checking `define`...
|
||||
--> $DIR/dont-remap-tait-substs.rs:15:1
|
||||
|
|
||||
LL | fn define<A, B: Send>(a: A, b: B) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
|
||||
note: cycle used when checking item types in top-level module
|
||||
--> $DIR/dont-remap-tait-substs.rs:8:1
|
||||
|
|
||||
LL | / #![feature(type_alias_impl_trait)]
|
||||
LL | |
|
||||
LL | | type Foo<T: Send, U> = impl NeedsSend<T>;
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | fn main() {}
|
||||
| |____________^
|
||||
|
||||
error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
|
||||
--> $DIR/dont-remap-tait-substs.rs:10:24
|
||||
|
|
||||
LL | type Foo<T: Send, U> = impl NeedsSend<T>;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires borrow-checking `define`...
|
||||
--> $DIR/dont-remap-tait-substs.rs:15:1
|
||||
|
|
||||
LL | fn define<A, B: Send>(a: A, b: B) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
|
||||
note: cycle used when checking item types in top-level module
|
||||
--> $DIR/dont-remap-tait-substs.rs:8:1
|
||||
|
|
||||
LL | / #![feature(type_alias_impl_trait)]
|
||||
LL | |
|
||||
LL | | type Foo<T: Send, U> = impl NeedsSend<T>;
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | fn main() {}
|
||||
| |____________^
|
||||
|
||||
error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
|
||||
--> $DIR/dont-remap-tait-substs.rs:10:24
|
||||
|
|
||||
LL | type Foo<T: Send, U> = impl NeedsSend<T>;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires borrow-checking `define`...
|
||||
--> $DIR/dont-remap-tait-substs.rs:15:1
|
||||
|
|
||||
LL | fn define<A, B: Send>(a: A, b: B) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
|
||||
note: cycle used when checking item types in top-level module
|
||||
--> $DIR/dont-remap-tait-substs.rs:8:1
|
||||
|
|
||||
LL | / #![feature(type_alias_impl_trait)]
|
||||
LL | |
|
||||
LL | | type Foo<T: Send, U> = impl NeedsSend<T>;
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | fn main() {}
|
||||
| |____________^
|
||||
|
||||
error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
|
||||
--> $DIR/dont-remap-tait-substs.rs:10:24
|
||||
|
|
||||
LL | type Foo<T: Send, U> = impl NeedsSend<T>;
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires borrow-checking `define`...
|
||||
--> $DIR/dont-remap-tait-substs.rs:15:1
|
||||
|
|
||||
LL | fn define<A, B: Send>(a: A, b: B) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
|
||||
note: cycle used when checking item types in top-level module
|
||||
--> $DIR/dont-remap-tait-substs.rs:8:1
|
||||
|
|
||||
LL | / #![feature(type_alias_impl_trait)]
|
||||
LL | |
|
||||
LL | | type Foo<T: Send, U> = impl NeedsSend<T>;
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | fn main() {}
|
||||
| |____________^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
|
@ -1,11 +1,10 @@
|
|||
// compile-flags: -Ztrait-solver=next
|
||||
// known-bug: unknown
|
||||
|
||||
trait Test {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
fn transform<T: Test>(x: T) -> T::Assoc {
|
||||
fn transform<T: Test>(x: Inv<T>) -> Inv<T::Assoc> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
@ -17,8 +16,13 @@ impl Test for String {
|
|||
type Assoc = String;
|
||||
}
|
||||
|
||||
struct Inv<T>(Option<*mut T>);
|
||||
|
||||
fn main() {
|
||||
let mut x = Default::default();
|
||||
let mut x: Inv<_> = Inv(None);
|
||||
// This ends up equating `Inv<?x>` with `Inv<<?x as Test>::Assoc>`
|
||||
// which fails the occurs check when generalizing `?x`.
|
||||
x = transform(x);
|
||||
x = 1i32;
|
||||
//~^ ERROR mismatched types
|
||||
x = Inv::<i32>(None);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/equating-projection-cyclically.rs:22:19
|
||||
--> $DIR/equating-projection-cyclically.rs:25:9
|
||||
|
|
||||
LL | x = transform(x);
|
||||
| ^ expected inferred type, found associated type
|
||||
|
|
||||
= note: expected type `_`
|
||||
found associated type `<_ as Test>::Assoc`
|
||||
= help: consider constraining the associated type `<_ as Test>::Assoc` to `_`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
| ^^^^^^^^^^^^ cyclic type of infinite size
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// check-pass
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
// Issue 95863
|
||||
// known-bug: #95863
|
||||
|
||||
pub trait With {
|
||||
type F;
|
||||
|
|
39
tests/ui/traits/new-solver/lazy-nested-obligations-2.stderr
Normal file
39
tests/ui/traits/new-solver/lazy-nested-obligations-2.stderr
Normal file
|
@ -0,0 +1,39 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/lazy-nested-obligations-2.rs:15:23
|
||||
|
|
||||
LL | let _: V<i32> = V(f);
|
||||
| - ^ types differ
|
||||
| |
|
||||
| arguments to this struct are incorrect
|
||||
|
|
||||
= note: expected associated type `<i32 as With>::F`
|
||||
found fn item `for<'a> fn(&'a str) {f}`
|
||||
= help: consider constraining the associated type `<i32 as With>::F` to `for<'a> fn(&'a str) {f}` or calling a method that returns `<i32 as With>::F`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
note: tuple struct defined here
|
||||
--> $DIR/lazy-nested-obligations-2.rs:16:16
|
||||
|
|
||||
LL | pub struct V<T: With>(<T as With>::F);
|
||||
| ^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/lazy-nested-obligations-2.rs:21:30
|
||||
|
|
||||
LL | let _: E3<i32> = E3::Var(f);
|
||||
| ------- ^ types differ
|
||||
| |
|
||||
| arguments to this enum variant are incorrect
|
||||
|
|
||||
= note: expected associated type `<i32 as With>::F`
|
||||
found fn item `for<'a> fn(&'a str) {f}`
|
||||
= help: consider constraining the associated type `<i32 as With>::F` to `for<'a> fn(&'a str) {f}` or calling a method that returns `<i32 as With>::F`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
note: tuple variant defined here
|
||||
--> $DIR/lazy-nested-obligations-2.rs:19:9
|
||||
|
|
||||
LL | Var(<T as With>::F),
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
|
@ -10,7 +10,15 @@ 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 `dyn Setup<From = T>: Setup` is not satisfied
|
||||
//~^ ERROR the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed
|
||||
//~| ERROR the trait bound `dyn Setup<From = T>: Setup` is not satisfied
|
||||
//~| ERROR mismatched types
|
||||
//~| ERROR mismatched types
|
||||
//~| ERROR the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
|
||||
//~| ERROR the size for values of type `<dyn Setup<From = T> as Setup>::From` cannot be known at compilation time
|
||||
|
||||
// FIXME(-Ztrait-solver=next): These error messages are horrible and some of them
|
||||
// are even simple fallout from previous error.
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -14,6 +14,65 @@ help: consider introducing a `where` clause, but there might be an alternative b
|
|||
LL | pub fn copy_any<T>(t: &T) -> T where dyn Setup<From = T>: Setup {
|
||||
| ++++++++++++++++++++++++++++++++
|
||||
|
||||
error: aborting due to previous error
|
||||
error: the type `&<dyn Setup<From = T> as Setup>::From` is not well-formed
|
||||
--> $DIR/object-unsafety.rs:12:31
|
||||
|
|
||||
LL | copy::<dyn Setup<From=T>>(t)
|
||||
| ^
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/object-unsafety.rs:12:31
|
||||
|
|
||||
LL | copy::<dyn Setup<From=T>>(t)
|
||||
| ------------------------- ^ types differ
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected reference `&<dyn Setup<From = T> as Setup>::From`
|
||||
found reference `&T`
|
||||
note: function defined here
|
||||
--> $DIR/object-unsafety.rs:7:4
|
||||
|
|
||||
LL | fn copy<U: Setup + ?Sized>(from: &U::From) -> U::From {
|
||||
| ^^^^ --------------
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/object-unsafety.rs:12:5
|
||||
|
|
||||
LL | pub fn copy_any<T>(t: &T) -> T {
|
||||
| - - expected `T` because of return type
|
||||
| |
|
||||
| this type parameter
|
||||
LL | copy::<dyn Setup<From=T>>(t)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
|
||||
|
|
||||
= note: expected type parameter `T`
|
||||
found associated type `<dyn Setup<From = T> as Setup>::From`
|
||||
= note: you might be missing a type parameter or trait bound
|
||||
|
||||
error: the type `<dyn Setup<From = T> as Setup>::From` is not well-formed
|
||||
--> $DIR/object-unsafety.rs:12:5
|
||||
|
|
||||
LL | copy::<dyn Setup<From=T>>(t)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the size for values of type `<dyn Setup<From = T> as Setup>::From` cannot be known at compilation time
|
||||
--> $DIR/object-unsafety.rs:12:5
|
||||
|
|
||||
LL | copy::<dyn Setup<From=T>>(t)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^---
|
||||
| |
|
||||
| doesn't have a size known at compile-time
|
||||
| this returned value is of type `<dyn Setup<From = T> as Setup>::From`
|
||||
|
|
||||
= help: the trait `Sized` is not implemented for `<dyn Setup<From = T> as Setup>::From`
|
||||
= note: the return type of a function must have a statically known size
|
||||
help: consider further restricting the associated type
|
||||
|
|
||||
LL | pub fn copy_any<T>(t: &T) -> T where <dyn Setup<From = T> as Setup>::From: Sized {
|
||||
| +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//~ ERROR overflow
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
|
||||
trait Foo1 {
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
|
||||
--> $DIR/recursive-self-normalization-2.rs:15:5
|
||||
--> $DIR/recursive-self-normalization-2.rs:16:5
|
||||
|
|
||||
LL | needs_bar::<T::Assoc1>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
|
||||
note: required by a bound in `needs_bar`
|
||||
--> $DIR/recursive-self-normalization-2.rs:12:17
|
||||
--> $DIR/recursive-self-normalization-2.rs:13:17
|
||||
|
|
||||
LL | fn needs_bar<S: Bar>() {}
|
||||
| ^^^ required by this bound in `needs_bar`
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo2>::Assoc2`
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization_2`)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
//~ ERROR overflow evaluating the requirement `<T as Foo>::Assoc` [E0275]
|
||||
// compile-flags: -Ztrait-solver=next
|
||||
|
||||
trait Foo {
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
|
||||
--> $DIR/recursive-self-normalization.rs:11:5
|
||||
--> $DIR/recursive-self-normalization.rs:12:5
|
||||
|
|
||||
LL | needs_bar::<T::Assoc>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
|
||||
note: required by a bound in `needs_bar`
|
||||
--> $DIR/recursive-self-normalization.rs:8:17
|
||||
--> $DIR/recursive-self-normalization.rs:9:17
|
||||
|
|
||||
LL | fn needs_bar<S: Bar>() {}
|
||||
| ^^^ required by this bound in `needs_bar`
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc`
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`recursive_self_normalization`)
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0271]: type mismatch resolving `[u8; 3] <: <Range<usize> as SliceIndex<[u8]>>::Output`
|
||||
error[E0271]: type mismatch resolving `[u8; 3] <: <[u8] as Index<Range<usize>>>::Output`
|
||||
--> $DIR/slice-match-byte-lit.rs:6:9
|
||||
|
|
||||
LL | match &s[0..3] {
|
||||
| -------- this expression has type `&<std::ops::Range<usize> as SliceIndex<[u8]>>::Output`
|
||||
| -------- this expression has type `&<[u8] as Index<std::ops::Range<usize>>>::Output`
|
||||
LL | b"uwu" => {}
|
||||
| ^^^^^^ types differ
|
||||
|
||||
|
|
|
@ -10,12 +10,11 @@ trait Default {
|
|||
}
|
||||
|
||||
impl<T> Default for T {
|
||||
default type Id = T;
|
||||
|
||||
fn intu(&self) -> &Self::Id {
|
||||
default type Id = T;
|
||||
// This will be fixed by #111994
|
||||
fn intu(&self) -> &Self::Id { //~ ERROR type annotations needed
|
||||
self
|
||||
//~^ ERROR cannot satisfy `T <: <T as Default>::Id`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
|
||||
|
@ -24,7 +23,6 @@ fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
|
|||
|
||||
use std::num::NonZeroU8;
|
||||
fn main() {
|
||||
let s = transmute::<u8, Option<NonZeroU8>>(0);
|
||||
//~^ ERROR cannot satisfy `<u8 as Default>::Id == Option<NonZeroU8>
|
||||
let s = transmute::<u8, Option<NonZeroU8>>(0); // this call should then error
|
||||
assert_eq!(s, None);
|
||||
}
|
||||
|
|
|
@ -8,24 +8,14 @@ LL | #![feature(specialization)]
|
|||
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `T <: <T as Default>::Id`
|
||||
--> $DIR/specialization-transmute.rs:16:9
|
||||
error[E0284]: type annotations needed
|
||||
--> $DIR/specialization-transmute.rs:15:23
|
||||
|
|
||||
LL | self
|
||||
| ^^^^ cannot satisfy `T <: <T as Default>::Id`
|
||||
LL | fn intu(&self) -> &Self::Id {
|
||||
| ^^^^^^^^^ cannot infer type
|
||||
|
|
||||
= note: cannot satisfy `<T as Default>::Id == _`
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `<u8 as Default>::Id == Option<NonZeroU8>`
|
||||
--> $DIR/specialization-transmute.rs:27:13
|
||||
|
|
||||
LL | let s = transmute::<u8, Option<NonZeroU8>>(0);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<u8 as Default>::Id == Option<NonZeroU8>`
|
||||
|
|
||||
note: required by a bound in `transmute`
|
||||
--> $DIR/specialization-transmute.rs:21:25
|
||||
|
|
||||
LL | fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
|
||||
| ^^^^^^ required by this bound in `transmute`
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
||||
|
|
|
@ -11,7 +11,7 @@ trait Default {
|
|||
}
|
||||
|
||||
impl<T> Default for T {
|
||||
default type Id = T;
|
||||
default type Id = T; //~ ERROR type annotations needed
|
||||
}
|
||||
|
||||
fn test<T: Default<Id = U>, U>() {}
|
||||
|
|
|
@ -8,6 +8,12 @@ LL | #![feature(specialization)]
|
|||
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/specialization-unconstrained.rs:14:22
|
||||
|
|
||||
LL | default type Id = T;
|
||||
| ^ cannot infer type for associated type `<T as Default>::Id`
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `<u32 as Default>::Id == ()`
|
||||
--> $DIR/specialization-unconstrained.rs:20:5
|
||||
|
|
||||
|
@ -20,6 +26,7 @@ note: required by a bound in `test`
|
|||
LL | fn test<T: Default<Id = U>, U>() {}
|
||||
| ^^^^^^ required by this bound in `test`
|
||||
|
||||
error: aborting due to previous error; 1 warning emitted
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
||||
Some errors have detailed explanations: E0282, E0284.
|
||||
For more information about an error, try `rustc --explain E0282`.
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
fn main() {
|
||||
type T = impl Copy;
|
||||
let foo: T = (1u32, 2u32);
|
||||
type Tait = impl Copy;
|
||||
let foo: Tait = (1u32, 2u32);
|
||||
let x: (_, _) = foo;
|
||||
println!("{:?}", x);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue