1
Fork 0

Revert "Auto merge of #92007 - oli-obk:lazy_tait2, r=nikomatsakis"

This reverts commit e7cc3bddbe, reversing
changes made to 734368a200.
This commit is contained in:
Oli Scherer 2022-02-11 07:18:06 +00:00
parent 2d8b8f3593
commit d54195db22
359 changed files with 2448 additions and 3311 deletions

View file

@ -4,7 +4,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
use rustc_hir::{self as hir, ExprKind};
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::traits::Obligation;
use rustc_middle::ty::{self, ToPredicate, Ty, TyS, TypeFoldable};
use rustc_middle::ty::{self, ToPredicate, Ty, TyS};
use rustc_span::{MultiSpan, Span};
use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
use rustc_trait_selection::traits::{
@ -98,7 +98,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
all_arms_diverge &= self.diverges.get();
let opt_suggest_box_span = self.opt_suggest_box_span(arm_ty, orig_expected);
let opt_suggest_box_span =
self.opt_suggest_box_span(arm.body.span, arm_ty, orig_expected);
let (arm_span, semi_span) =
self.get_appropriate_arm_semicolon_removal_span(&arms, i, prior_arm_ty, arm_ty);
@ -503,15 +504,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// provide a structured suggestion in that case.
pub(crate) fn opt_suggest_box_span(
&self,
span: Span,
outer_ty: &'tcx TyS<'tcx>,
orig_expected: Expectation<'tcx>,
) -> Option<Span> {
match orig_expected {
Expectation::ExpectHasType(expected)
if self.in_tail_expr
&& self.ret_coercion.as_ref()?.borrow().merged_ty().has_opaque_types()
&& self.can_coerce(outer_ty, expected) =>
match (orig_expected, self.ret_coercion_impl_trait.map(|ty| (self.body_id.owner, ty))) {
(Expectation::ExpectHasType(expected), Some((_id, ty)))
if self.in_tail_expr && self.can_coerce(outer_ty, expected) =>
{
let impl_trait_ret_ty =
self.infcx.instantiate_opaque_types(self.body_id, self.param_env, ty, span);
assert!(
impl_trait_ret_ty.obligations.is_empty(),
"we should never get new obligations here"
);
let obligations = self.fulfillment_cx.borrow().pending_obligations();
let mut suggest_box = !obligations.is_empty();
for o in obligations {

View file

@ -545,7 +545,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected: Expectation<'tcx>,
fn_sig: ty::FnSig<'tcx>,
) -> Ty<'tcx> {
// `fn_sig` is the *signature* of the closure being called. We
// `fn_sig` is the *signature* of the cosure being called. We
// don't know the full details yet (`Fn` vs `FnMut` etc), but we
// do know the types expected for each argument and the return
// type.

View file

@ -17,7 +17,7 @@ use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::layout::MAX_SIMD_LANES;
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{self, ParamEnv, RegionKind, Ty, TyCtxt};
use rustc_middle::ty::{self, OpaqueTypeKey, ParamEnv, RegionKind, Ty, TyCtxt};
use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
use rustc_span::symbol::sym;
use rustc_span::{self, MultiSpan, Span};
@ -81,6 +81,8 @@ pub(super) fn check_fn<'a, 'tcx>(
can_be_generator: Option<hir::Movability>,
return_type_pre_known: bool,
) -> (FnCtxt<'a, 'tcx>, Option<GeneratorTypes<'tcx>>) {
let mut fn_sig = fn_sig;
// Create the function context. This is either derived from scratch or,
// in the case of closures, based on the outer context.
let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
@ -93,8 +95,21 @@ pub(super) fn check_fn<'a, 'tcx>(
let declared_ret_ty = fn_sig.output();
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(declared_ret_ty)));
let revealed_ret_ty =
fcx.instantiate_opaque_types_from_value(declared_ret_ty, decl.output.span());
debug!("check_fn: declared_ret_ty: {}, revealed_ret_ty: {}", declared_ret_ty, revealed_ret_ty);
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty)));
fcx.ret_type_span = Some(decl.output.span());
if let ty::Opaque(..) = declared_ret_ty.kind() {
fcx.ret_coercion_impl_trait = Some(declared_ret_ty);
}
fn_sig = tcx.mk_fn_sig(
fn_sig.inputs().iter().cloned(),
revealed_ret_ty,
fn_sig.c_variadic,
fn_sig.unsafety,
fn_sig.abi,
);
let span = body.value.span;
@ -236,7 +251,7 @@ pub(super) fn check_fn<'a, 'tcx>(
fcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span });
debug!("actual_return_ty replaced with {:?}", actual_return_ty);
}
fcx.demand_suptype(span, declared_ret_ty, actual_return_ty);
fcx.demand_suptype(span, revealed_ret_ty, actual_return_ty);
// Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
if let Some(panic_impl_did) = tcx.lang_items().panic_impl() {
@ -614,8 +629,6 @@ fn check_opaque_meets_bounds<'tcx>(
span: Span,
origin: &hir::OpaqueTyOrigin,
) {
let hidden_type = tcx.type_of(def_id).subst(tcx, substs);
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let defining_use_anchor = match *origin {
hir::OpaqueTyOrigin::FnReturn(did) | hir::OpaqueTyOrigin::AsyncFn(did) => did,
@ -630,12 +643,24 @@ fn check_opaque_meets_bounds<'tcx>(
let misc_cause = traits::ObligationCause::misc(span, hir_id);
match infcx.at(&misc_cause, param_env).eq(opaque_ty, hidden_type) {
Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok),
Err(ty_err) => tcx.sess.delay_span_bug(
span,
&format!("could not unify `{}` with revealed type:\n{}", hidden_type, ty_err,),
),
let _ = inh.register_infer_ok_obligations(
infcx.instantiate_opaque_types(hir_id, param_env, opaque_ty, span),
);
let opaque_type_map = infcx.inner.borrow().opaque_types.clone();
for (OpaqueTypeKey { def_id, substs }, opaque_defn) in opaque_type_map {
let hidden_type = tcx.type_of(def_id).subst(tcx, substs);
trace!(?hidden_type);
match infcx.at(&misc_cause, param_env).eq(opaque_defn.concrete_ty, hidden_type) {
Ok(infer_ok) => inh.register_infer_ok_obligations(infer_ok),
Err(ty_err) => tcx.sess.delay_span_bug(
span,
&format!(
"could not check bounds on revealed type `{}`:\n{}",
hidden_type, ty_err,
),
),
}
}
// Check that all obligations are satisfied by the implementation's
@ -647,7 +672,7 @@ fn check_opaque_meets_bounds<'tcx>(
match origin {
// Checked when type checking the function containing them.
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {}
hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => return,
// Can have different predicates to their defining use
hir::OpaqueTyOrigin::TyAlias => {
// Finally, resolve all regions. This catches wily misuses of
@ -656,9 +681,6 @@ fn check_opaque_meets_bounds<'tcx>(
fcx.regionck_item(hir_id, span, FxHashSet::default());
}
}
// Clean up after ourselves
let _ = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
});
}

View file

@ -3,20 +3,16 @@
use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
use crate::astconv::AstConv;
use crate::rustc_middle::ty::subst::Subst;
use hir::OpaqueTyOrigin;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_hir::lang_items::LangItem;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_infer::infer::{InferOk, InferResult};
use rustc_infer::traits::ObligationCause;
use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::{self, Ty};
use rustc_span::source_map::Span;
use rustc_span::DUMMY_SP;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits::error_reporting::ArgKind;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
@ -176,29 +172,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
expected_ty: Ty<'tcx>,
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
match *expected_ty.kind() {
ty::Opaque(def_id, substs) => {
let bounds = self.tcx.explicit_item_bounds(def_id);
let sig = bounds.iter().find_map(|(pred, span)| match pred.kind().skip_binder() {
ty::PredicateKind::Projection(proj_predicate) => self
.deduce_sig_from_projection(
Some(*span),
pred.kind().rebind(proj_predicate.subst(self.tcx, substs)),
),
_ => None,
});
let kind = bounds
.iter()
.filter_map(|(pred, _)| match pred.kind().skip_binder() {
ty::PredicateKind::Trait(tp) => {
self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
}
_ => None,
})
.fold(None, |best, cur| Some(best.map_or(cur, |best| cmp::min(best, cur))));
trace!(?sig, ?kind);
(sig, kind)
}
ty::Dynamic(ref object_type, ..) => {
let sig = object_type.projection_bounds().find_map(|pb| {
let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
@ -224,7 +197,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
let expected_sig =
self.obligations_for_self_ty(expected_vid).find_map(|(_, obligation)| {
debug!(?obligation.predicate);
debug!(
"deduce_expectations_from_obligations: obligation.predicate={:?}",
obligation.predicate
);
let bound_predicate = obligation.predicate.kind();
if let ty::PredicateKind::Projection(proj_predicate) =
@ -425,14 +401,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// in this binder we are creating.
assert!(!expected_sig.sig.skip_binder().has_vars_bound_above(ty::INNERMOST));
let bound_sig = expected_sig.sig.map_bound(|sig| {
let output = self.hide_parent_opaque_types(
sig.output(),
expected_sig.cause_span.unwrap_or(DUMMY_SP),
body.id().hir_id,
);
self.tcx.mk_fn_sig(
sig.inputs().iter().cloned(),
output,
sig.output(),
sig.c_variadic,
hir::Unsafety::Normal,
Abi::RustCall,
@ -619,8 +590,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => astconv.ty_infer(None, decl.output.span()),
},
};
let supplied_return =
self.hide_parent_opaque_types(supplied_return, decl.output.span(), body.id().hir_id);
let result = ty::Binder::bind_with_vars(
self.tcx.mk_fn_sig(
@ -641,57 +610,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
result
}
fn hide_parent_opaque_types(&self, ty: Ty<'tcx>, span: Span, body_id: hir::HirId) -> Ty<'tcx> {
ty.fold_with(&mut ty::fold::BottomUpFolder {
tcx: self.infcx.tcx,
lt_op: |lt| lt,
ct_op: |ct| ct,
ty_op: |ty| match *ty.kind() {
// Closures can't create hidden types for opaque types of their parent, as they
// do not have all the outlives information available. Also `type_of` looks for
// hidden types in the owner (so the closure's parent), so it would not find these
// definitions.
ty::Opaque(def_id, _substs)
if matches!(
self.infcx.opaque_type_origin(def_id, DUMMY_SP),
Some(OpaqueTyOrigin::FnReturn(..))
) =>
{
let ty_var = self.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::TypeInference,
span,
});
let cause = ObligationCause::misc(span, body_id);
self.register_predicates(vec![self.infcx.opaque_ty_obligation(
ty,
ty_var,
true,
self.param_env,
cause,
)]);
ty_var
}
_ => ty,
},
})
}
/// Invoked when we are translating the generator that results
/// from desugaring an `async fn`. Returns the "sugared" return
/// type of the `async fn` -- that is, the return type that the
/// user specified. The "desugared" return type is an `impl
/// Future<Output = T>`, so we do this by searching through the
/// obligations to extract the `T`.
#[instrument(skip(self), level = "debug")]
fn deduce_future_output_from_obligations(&self, expr_def_id: DefId) -> Option<Ty<'tcx>> {
debug!("deduce_future_output_from_obligations(expr_def_id={:?})", expr_def_id);
let ret_coercion = self.ret_coercion.as_ref().unwrap_or_else(|| {
span_bug!(self.tcx.def_span(expr_def_id), "async fn generator outside of a fn")
});
// In practice, the return type of the surrounding function is
// always a (not yet resolved) inference variable, because it
// is the hidden type for an `impl Trait` that we are going to
// be inferring.
let ret_ty = ret_coercion.borrow().expected_ty();
let ret_ty = self.inh.infcx.shallow_resolve(ret_ty);
let (def_id, substs) = match *ret_ty.kind() {
ty::Opaque(def_id, substs) => (def_id, substs),
let ret_vid = match *ret_ty.kind() {
ty::Infer(ty::TyVar(ret_vid)) => ret_vid,
ty::Error(_) => return None,
_ => span_bug!(
self.tcx.def_span(expr_def_id),
@ -699,19 +638,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
),
};
let item_bounds = self.tcx.explicit_item_bounds(def_id);
// Search for a pending obligation like
//
// `<R as Future>::Output = T`
//
// where R is the return type we are expecting. This type `T`
// will be our output.
let output_ty = item_bounds.iter().find_map(|&(predicate, span)| {
let bound_predicate = predicate.subst(self.tcx, substs).kind();
let output_ty = self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
let bound_predicate = obligation.predicate.kind();
if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() {
self.deduce_future_output_from_projection(
span,
obligation.cause.span,
bound_predicate.rebind(proj_predicate),
)
} else {

View file

@ -1275,7 +1275,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
/// Returns the current "merged type", representing our best-guess
/// at the LUB of the expressions we've seen so far (if any). This
/// isn't *final* until you call `self.complete()`, which will return
/// isn't *final* until you call `self.final()`, which will return
/// the merged type.
pub fn merged_ty(&self) -> Ty<'tcx> {
self.final_ty.unwrap_or(self.expected_ty)

View file

@ -1,6 +1,5 @@
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::ty::{self, Ty};
use rustc_span::DUMMY_SP;
use rustc_span::{self, Span};
use super::Expectation::*;
@ -44,7 +43,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
// when checking the 'then' block which are incompatible with the
// 'else' branch.
pub(super) fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
match self.strip_opaque(fcx) {
match *self {
ExpectHasType(ety) => {
let ety = fcx.shallow_resolve(ety);
if !ety.is_ty_var() { ExpectHasType(ety) } else { NoExpectation }
@ -105,35 +104,14 @@ impl<'a, 'tcx> Expectation<'tcx> {
/// for the program to type-check). `only_has_type` will return
/// such a constraint, if it exists.
pub(super) fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
match self.strip_opaque(fcx) {
ExpectHasType(ty) => Some(ty),
match self {
ExpectHasType(ty) => Some(fcx.resolve_vars_if_possible(ty)),
NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) | IsLast(_) => {
None
}
}
}
/// We must not treat opaque types as expected types in their defining scope, as that
/// will break `fn foo() -> impl Trait { if cond { a } else { b } }` if `a` and `b` are
/// only "equal" if they coerce to a common target, like two different function items
/// coercing to a function pointer if they have the same signature.
fn strip_opaque(self, fcx: &FnCtxt<'a, 'tcx>) -> Self {
match self {
ExpectHasType(ty) => {
let ty = fcx.resolve_vars_if_possible(ty);
match *ty.kind() {
ty::Opaque(def_id, _)
if fcx.infcx.opaque_type_origin(def_id, DUMMY_SP).is_some() =>
{
NoExpectation
}
_ => self,
}
}
_ => self,
}
}
/// Like `only_has_type`, but instead of returning `None` if no
/// hard constraint exists, creates a fresh type variable.
pub(super) fn coercion_target_type(self, fcx: &FnCtxt<'a, 'tcx>, span: Span) -> Ty<'tcx> {

View file

@ -956,7 +956,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
let else_diverges = self.diverges.get();
let opt_suggest_box_span = self.opt_suggest_box_span(else_ty, orig_expected);
let opt_suggest_box_span =
self.opt_suggest_box_span(else_expr.span, else_ty, orig_expected);
let if_cause =
self.if_cause(sp, then_expr, else_expr, then_ty, else_ty, opt_suggest_box_span);

View file

@ -24,7 +24,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
self.fulfillment_cx.borrow_mut().pending_obligations()
);
// Check if we have any unsolved variables. If not, no need for fallback.
// Check if we have any unsolved varibales. If not, no need for fallback.
let unsolved_variables = self.unsolved_variables();
if unsolved_variables.is_empty() {
return false;
@ -66,6 +66,16 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
// refer to opaque types.
self.select_obligations_where_possible(fallback_has_occurred, |_| {});
// We now run fallback again, but this time we allow it to replace
// unconstrained opaque type variables, in addition to performing
// other kinds of fallback.
for ty in &self.unsolved_variables() {
fallback_has_occurred |= self.fallback_opaque_type_vars(ty);
}
// See if we can make any more progress.
self.select_obligations_where_possible(fallback_has_occurred, |_| {});
fallback_has_occurred
}
@ -126,6 +136,59 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
true
}
/// Second round of fallback: Unconstrained type variables created
/// from the instantiation of an opaque type fall back to the
/// opaque type itself. This is a somewhat incomplete attempt to
/// manage "identity passthrough" for `impl Trait` types.
///
/// For example, in this code:
///
///```
/// type MyType = impl Copy;
/// fn defining_use() -> MyType { true }
/// fn other_use() -> MyType { defining_use() }
/// ```
///
/// `defining_use` will constrain the instantiated inference
/// variable to `bool`, while `other_use` will constrain
/// the instantiated inference variable to `MyType`.
///
/// When we process opaque types during writeback, we
/// will handle cases like `other_use`, and not count
/// them as defining usages
///
/// However, we also need to handle cases like this:
///
/// ```rust
/// pub type Foo = impl Copy;
/// fn produce() -> Option<Foo> {
/// None
/// }
/// ```
///
/// In the above snippet, the inference variable created by
/// instantiating `Option<Foo>` will be completely unconstrained.
/// We treat this as a non-defining use by making the inference
/// variable fall back to the opaque type itself.
fn fallback_opaque_type_vars(&self, ty: Ty<'tcx>) -> bool {
let span = self
.infcx
.type_var_origin(ty)
.map(|origin| origin.span)
.unwrap_or(rustc_span::DUMMY_SP);
let oty = self.inner.borrow().opaque_types_vars.get(ty).copied();
if let Some(opaque_ty) = oty {
debug!(
"fallback_opaque_type_vars(ty={:?}): falling back to opaque type {:?}",
ty, opaque_ty
);
self.demand_eqtype(span, ty, opaque_ty);
true
} else {
return false;
}
}
/// The "diverging fallback" system is rather complicated. This is
/// a result of our need to balance 'do the right thing' with
/// backwards compatibility.

View file

@ -367,6 +367,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(result, spans)
}
/// Replaces the opaque types from the given value with type variables,
/// and records the `OpaqueTypeMap` for later use during writeback. See
/// `InferCtxt::instantiate_opaque_types` for more details.
#[instrument(skip(self, value_span), level = "debug")]
pub(in super::super) fn instantiate_opaque_types_from_value<T: TypeFoldable<'tcx>>(
&self,
value: T,
value_span: Span,
) -> T {
self.register_infer_ok_obligations(self.instantiate_opaque_types(
self.body_id,
self.param_env,
value,
value_span,
))
}
/// Convenience method which tracks extra diagnostic information for normalization
/// that occurs as a result of WF checking. The `hir_id` is the `HirId` of the hir item
/// whose type is being wf-checked - this is used to construct a more precise span if
@ -703,7 +720,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// inference variable.
ty::PredicateKind::ClosureKind(..) => None,
ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
ty::PredicateKind::OpaqueType(..) => None,
}
})
.filter(move |(tr, _)| self.self_type_matches_expected_vid(*tr, ty_var_root))

View file

@ -57,6 +57,8 @@ pub struct FnCtxt<'a, 'tcx> {
/// any).
pub(super) ret_coercion: Option<RefCell<DynamicCoerceMany<'tcx>>>,
pub(super) ret_coercion_impl_trait: Option<Ty<'tcx>>,
pub(super) ret_type_span: Option<Span>,
/// Used exclusively to reduce cost of advanced evaluation used for
@ -128,6 +130,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
param_env,
err_count_on_creation: inh.tcx.sess.err_count(),
ret_coercion: None,
ret_coercion_impl_trait: None,
ret_type_span: None,
in_tail_expr: false,
ret_coercion_span: Cell::new(None),

View file

@ -95,13 +95,6 @@ impl<'tcx> InheritedBuilder<'tcx> {
let def_id = self.def_id;
self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id)))
}
/// WF-checking doesn't need to recompute opaque types and can instead use
/// the type_of query to get them from typeck.
pub fn reveal_defining_opaque_types(mut self) -> Self {
self.infcx = self.infcx.reveal_defining_opaque_types();
self
}
}
impl<'a, 'tcx> Inherited<'a, 'tcx> {
@ -126,8 +119,8 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
}
}
#[instrument(level = "debug", skip(self))]
pub(super) fn register_predicate(&self, obligation: traits::PredicateObligation<'tcx>) {
debug!("register_predicate({:?})", obligation);
if obligation.has_escaping_bound_vars() {
span_bug!(obligation.cause.span, "escaping bound vars in predicate {:?}", obligation);
}

View file

@ -856,7 +856,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
| ty::PredicateKind::TypeOutlives(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::OpaqueType(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
}
});
@ -1476,7 +1475,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
TraitCandidate(trait_ref) => self.probe(|_| {
let _ = self
.at(&ObligationCause::dummy(), self.param_env)
.define_opaque_types(false)
.sup(candidate.xform_self_ty, self_ty);
match self.select_trait_candidate(trait_ref) {
Ok(Some(traits::ImplSource::UserDefined(ref impl_data))) => {
@ -1506,7 +1504,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// First check that the self type can be related.
let sub_obligations = match self
.at(&ObligationCause::dummy(), self.param_env)
.define_opaque_types(false)
.sup(probe.xform_self_ty, self_ty)
{
Ok(InferOk { obligations, value: () }) => obligations,
@ -1654,7 +1651,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
);
if self
.at(&ObligationCause::dummy(), self.param_env)
.define_opaque_types(false)
.sup(return_ty, xform_ret_ty)
.is_err()
{

View file

@ -341,7 +341,6 @@ fn diagnostic_only_typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::T
typeck_with_fallback(tcx, def_id, fallback)
}
#[instrument(skip(tcx, fallback))]
fn typeck_with_fallback<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,

View file

@ -335,6 +335,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Returns a list of `Ty`s for each upvar.
fn final_upvar_tys(&self, closure_id: DefId) -> Vec<Ty<'tcx>> {
// Presently an unboxed closure type cannot "escape" out of a
// function, so we will only encounter ones that originated in the
// local crate or were inlined into it along with some function.
// This may change if abstract return types of some sort are
// implemented.
self.typeck_results
.borrow()
.closure_min_captures_flattened(closure_id)

View file

@ -895,7 +895,7 @@ fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder<
fn for_id(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> CheckWfFcxBuilder<'_> {
CheckWfFcxBuilder {
inherited: Inherited::build(tcx, def_id).reveal_defining_opaque_types(),
inherited: Inherited::build(tcx, def_id),
id: hir::HirId::make_owner(def_id),
span,
param_env: tcx.param_env(def_id),

View file

@ -18,6 +18,7 @@ use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt};
use rustc_span::symbol::sym;
use rustc_span::Span;
use rustc_trait_selection::opaque_types::InferCtxtExt;
use std::mem;
@ -64,7 +65,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
wbcx.visit_closures();
wbcx.visit_liberated_fn_sigs();
wbcx.visit_fru_field_types();
wbcx.visit_opaque_types();
wbcx.visit_opaque_types(body.value.span);
wbcx.visit_coercion_casts();
wbcx.visit_user_provided_tys();
wbcx.visit_user_provided_sigs();
@ -495,18 +496,64 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
fcx_typeck_results.generator_interior_types.clone();
}
#[instrument(skip(self), level = "debug")]
fn visit_opaque_types(&mut self) {
let opaque_types =
self.fcx.infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
for (opaque_type_key, decl) in opaque_types {
let hidden_type = match decl.origin {
hir::OpaqueTyOrigin::FnReturn(_) | hir::OpaqueTyOrigin::AsyncFn(_) => {
Some(self.resolve(decl.hidden_type.ty, &decl.hidden_type.span))
#[instrument(skip(self, span), level = "debug")]
fn visit_opaque_types(&mut self, span: Span) {
let opaque_types = self.fcx.infcx.inner.borrow().opaque_types.clone();
for (opaque_type_key, opaque_defn) in opaque_types {
let hir_id =
self.tcx().hir().local_def_id_to_hir_id(opaque_type_key.def_id.expect_local());
let instantiated_ty = self.resolve(opaque_defn.concrete_ty, &hir_id);
debug_assert!(!instantiated_ty.has_escaping_bound_vars());
let opaque_type_key = self.fcx.fully_resolve(opaque_type_key).unwrap();
// Prevent:
// * `fn foo<T>() -> Foo<T>`
// * `fn foo<T: Bound + Other>() -> Foo<T>`
// from being defining.
// Also replace all generic params with the ones from the opaque type
// definition so that
// ```rust
// type Foo<T> = impl Baz + 'static;
// fn foo<U>() -> Foo<U> { .. }
// ```
// figures out the concrete type with `U`, but the stored type is with `T`.
// FIXME: why are we calling this here? This seems too early, and duplicated.
let definition_ty = self.fcx.infer_opaque_definition_from_instantiation(
opaque_type_key,
instantiated_ty,
span,
);
let mut skip_add = false;
if let ty::Opaque(definition_ty_def_id, _substs) = *definition_ty.kind() {
if opaque_defn.origin == hir::OpaqueTyOrigin::TyAlias {
if opaque_type_key.def_id == definition_ty_def_id {
debug!(
"skipping adding concrete definition for opaque type {:?} {:?}",
opaque_defn, opaque_type_key.def_id
);
skip_add = true;
}
}
hir::OpaqueTyOrigin::TyAlias => None,
};
self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id, hidden_type);
}
if opaque_type_key.substs.needs_infer() {
span_bug!(span, "{:#?} has inference variables", opaque_type_key.substs)
}
// We only want to add an entry into `concrete_opaque_types`
// if we actually found a defining usage of this opaque type.
// Otherwise, we do nothing - we'll either find a defining usage
// in some other location, or we'll end up emitting an error due
// to the lack of defining usage
if !skip_add {
self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id);
}
}
}

View file

@ -389,22 +389,28 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
.get_value_matching(|(key, _)| key.def_id == def_id.to_def_id())
.copied()
.unwrap_or_else(|| {
let table = tcx.typeck(owner);
if let Some(ErrorReported) = table.tainted_by_errors {
tcx.sess.delay_span_bug(
DUMMY_SP,
&format!(
"owner {:?} has no opaque type for {:?} in its typeck results",
owner, def_id,
),
);
if let Some(ErrorReported) =
tcx.typeck(owner).tainted_by_errors
{
// Some error in the
// owner fn prevented us from populating
// the `concrete_opaque_types` table.
tcx.ty_error()
} else {
table.concrete_opaque_types.get(&def_id.to_def_id()).copied().unwrap_or_else(|| {
// We failed to resolve the opaque type or it
// resolves to itself. We interpret this as the
// no values of the hidden type ever being constructed,
// so we can just make the hidden type be `!`.
// For backwards compatibility reasons, we fall back to
// `()` until we the diverging default is changed.
Some(tcx.mk_diverging_default())
}).expect("RPIT always have a hidden type from typeck")
// We failed to resolve the opaque type or it
// resolves to itself. Return the non-revealed
// type, which should result in E0720.
tcx.mk_opaque(
def_id.to_def_id(),
InternalSubsts::identity_for_item(tcx, def_id.to_def_id()),
)
}
});
debug!("concrete_ty = {:?}", concrete_ty);
@ -598,21 +604,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
}
// Calling `mir_borrowck` can lead to cycle errors through
// const-checking, avoid calling it if we don't have to.
// ```rust
// type Foo = impl Fn() -> usize; // when computing type for this
// const fn bar() -> Foo {
// || 0usize
// }
// const BAZR: Foo = bar(); // we would mir-borrowck this, causing cycles
// // because we again need to reveal `Foo` so we can check whether the
// // constant does not contain interior mutability.
// ```
let tables = self.tcx.typeck(def_id);
if let Some(_) = tables.tainted_by_errors {
self.found = Some((DUMMY_SP, self.tcx.ty_error()));
return;
}
if tables.concrete_opaque_types.get(&self.def_id).is_none() {
if !self.tcx.typeck(def_id).concrete_opaque_types.contains(&self.def_id) {
debug!("no constraints in typeck results");
return;
}
@ -666,7 +658,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
intravisit::walk_expr(self, ex);
}
fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
trace!(?it.def_id);
debug!("find_existential_constraints: visiting {:?}", it);
// The opaque type itself or its children are not within its reveal scope.
if it.def_id.to_def_id() != self.def_id {
self.check(it.def_id);
@ -674,7 +666,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
}
}
fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
trace!(?it.def_id);
debug!("find_existential_constraints: visiting {:?}", it);
// The opaque type itself or its children are not within its reveal scope.
if it.def_id.to_def_id() != self.def_id {
self.check(it.def_id);
@ -682,7 +674,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
}
}
fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
trace!(?it.def_id);
debug!("find_existential_constraints: visiting {:?}", it);
self.check(it.def_id);
intravisit::walk_trait_item(self, it);
}
@ -692,12 +684,12 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
let scope = tcx.hir().get_defining_scope(hir_id);
let mut locator = ConstraintLocator { def_id: def_id.to_def_id(), tcx, found: None };
debug!(?scope);
debug!("find_opaque_ty_constraints: scope={:?}", scope);
if scope == hir::CRATE_HIR_ID {
tcx.hir().walk_toplevel_module(&mut locator);
} else {
trace!("scope={:#?}", tcx.hir().get(scope));
debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope));
match tcx.hir().get(scope) {
// We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
// This allows our visitor to process the defining item itself, causing
@ -724,12 +716,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
Some((_, ty)) => ty,
None => {
let span = tcx.def_span(def_id);
let name = tcx.item_name(tcx.parent(def_id.to_def_id()).unwrap());
let label = format!(
"`{}` must be used in combination with a concrete type within the same module",
name
);
tcx.sess.struct_span_err(span, "unconstrained opaque type").note(&label).emit();
tcx.sess.span_err(span, "could not find defining uses");
tcx.ty_error()
}
}

View file

@ -427,7 +427,6 @@ fn trait_predicate_kind<'tcx>(
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::OpaqueType(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => None,
}
}

View file

@ -59,7 +59,6 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::OpaqueType(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => (),
}
}