Skip to content

use evaluate_obligation to decide when to do unsized coercions #50753

Open
@nikomatsakis

Description

@nikomatsakis

As part of the coercion logic, we sometimes invoke coerce_unsized:

fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tcx> {

This would e.g. coerce from &[T; 32] to &[T] or from Arc<T> to Arc<dyn Trait> where T: Trait. To decide whether or not we are going to do this, we want to check if Arc<T>: CoerceUnsized<Arc<dyn Trait>> is implemented (or something like that). We do this in this funky little loop here:

let mut selcx = traits::SelectionContext::new(self);
// Use a FIFO queue for this custom fulfillment procedure.
let mut queue = VecDeque::new();
// Create an obligation for `Source: CoerceUnsized<Target>`.
let cause = ObligationCause::misc(self.cause.span, self.body_id);
queue.push_back(self.tcx.predicate_for_trait_def(self.fcx.param_env,
cause,
coerce_unsized_did,
0,
coerce_source,
&[coerce_target]));
let mut has_unsized_tuple_coercion = false;

This kind of pulls out all the (transitive) requires to prove CoerceUnsized and ignores the rest. However, if we ever hope to define coercions in terms of the trait system, what we really ought to be doing is using an evaluate_obligation check.

Hopefully we can get away with this backwards compatibly.

@eddyb told me at some point -- iirc -- that the reason this loop exists is for diagnostics. So making this change may require some work on that point.

cc @leodasvacas @mikeyhew

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-coercionsArea: implicit and explicit `expr as Type` coercionsA-trait-systemArea: Trait systemC-enhancementCategory: An issue proposing an enhancement or a PR with one.S-types-trackedStatus: Being actively tracked by the types teamT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions