1
Fork 0

Auto merge of #87141 - spastorino:remove_impl_trait_in_bindings, r=oli-obk

Remove impl trait in bindings

Closes #86729

r? `@oli-obk`
This commit is contained in:
bors 2021-07-20 05:34:22 +00:00
commit a72c360a30
113 changed files with 540 additions and 1954 deletions

View file

@ -221,9 +221,7 @@ pub(super) fn check_fn<'a, 'tcx>(
fcx.resume_yield_tys = Some((resume_ty, yield_ty));
}
let outer_def_id = tcx.closure_base_def_id(hir.local_def_id(fn_id).to_def_id()).expect_local();
let outer_hir_id = hir.local_def_id_to_hir_id(outer_def_id);
GatherLocalsVisitor::new(&fcx, outer_hir_id).visit_body(body);
GatherLocalsVisitor::new(&fcx).visit_body(body);
// C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
// (as it's created inside the body itself, not passed in from outside).
@ -665,13 +663,9 @@ pub(super) fn check_opaque_for_cycles<'tcx>(
span: Span,
origin: &hir::OpaqueTyOrigin,
) -> Result<(), ErrorReported> {
if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs)
{
if tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs).is_err() {
match origin {
hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span),
hir::OpaqueTyOrigin::Binding => {
binding_opaque_type_cycle_error(tcx, def_id, span, partially_expanded_type)
}
_ => opaque_type_cycle_error(tcx, def_id, span),
}
Err(ErrorReported)
@ -704,8 +698,7 @@ fn check_opaque_meets_bounds<'tcx>(
// Checked when type checking the function containing them.
hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return,
// Can have different predicates to their defining use
hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias => {
}
hir::OpaqueTyOrigin::TyAlias => {}
}
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);

View file

@ -4,12 +4,11 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::PatKind;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
use rustc_middle::ty::Ty;
use rustc_span::{sym, Span};
use rustc_span::Span;
use rustc_trait_selection::traits;
pub(super) struct GatherLocalsVisitor<'a, 'tcx> {
fcx: &'a FnCtxt<'a, 'tcx>,
parent_id: hir::HirId,
// parameters are special cases of patterns, but we want to handle them as
// *distinct* cases. so track when we are hitting a pattern *within* an fn
// parameter.
@ -17,8 +16,8 @@ pub(super) struct GatherLocalsVisitor<'a, 'tcx> {
}
impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
pub(super) fn new(fcx: &'a FnCtxt<'a, 'tcx>, parent_id: hir::HirId) -> Self {
Self { fcx, parent_id, outermost_fn_param_pat: None }
pub(super) fn new(fcx: &'a FnCtxt<'a, 'tcx>) -> Self {
Self { fcx, outermost_fn_param_pat: None }
}
fn assign(&mut self, span: Span, nid: hir::HirId, ty_opt: Option<LocalTy<'tcx>>) -> Ty<'tcx> {
@ -57,26 +56,15 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
Some(ref ty) => {
let o_ty = self.fcx.to_ty(&ty);
let revealed_ty = self.fcx.instantiate_opaque_types_from_value(
self.parent_id,
o_ty,
ty.span,
Some(sym::impl_trait_in_bindings),
);
let c_ty =
self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(revealed_ty));
debug!(
"visit_local: ty.hir_id={:?} o_ty={:?} revealed_ty={:?} c_ty={:?}",
ty.hir_id, o_ty, revealed_ty, c_ty
);
let c_ty = self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(o_ty));
debug!("visit_local: ty.hir_id={:?} o_ty={:?} c_ty={:?}", ty.hir_id, o_ty, c_ty);
self.fcx
.typeck_results
.borrow_mut()
.user_provided_types_mut()
.insert(ty.hir_id, c_ty);
Some(LocalTy { decl_ty: o_ty, revealed_ty })
Some(LocalTy { decl_ty: o_ty, revealed_ty: o_ty })
}
None => None,
};

View file

@ -118,9 +118,9 @@ use rustc_middle::ty::{self, Ty, TyCtxt, UserType};
use rustc_session::config;
use rustc_session::parse::feature_err;
use rustc_session::Session;
use rustc_span::source_map::DUMMY_SP;
use rustc_span::symbol::{kw, Ident};
use rustc_span::{self, BytePos, MultiSpan, Span};
use rustc_span::{source_map::DUMMY_SP, sym};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi::Abi;
use rustc_trait_selection::traits;
@ -441,19 +441,12 @@ fn typeck_with_fallback<'tcx>(
let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type);
fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
let revealed_ty = fcx.instantiate_opaque_types_from_value(
id,
expected_type,
body.value.span,
Some(sym::impl_trait_in_bindings),
);
// Gather locals in statics (because of block expressions).
GatherLocalsVisitor::new(&fcx, id).visit_body(body);
GatherLocalsVisitor::new(&fcx).visit_body(body);
fcx.check_expr_coercable_to_type(&body.value, revealed_ty, None);
fcx.check_expr_coercable_to_type(&body.value, expected_type, None);
fcx.write_ty(id, revealed_ty);
fcx.write_ty(id, expected_type);
fcx
};
@ -573,66 +566,6 @@ fn get_owner_return_paths(
})
}
/// Emit an error for recursive opaque types in a `let` binding.
fn binding_opaque_type_cycle_error(
tcx: TyCtxt<'tcx>,
def_id: LocalDefId,
span: Span,
partially_expanded_type: Ty<'tcx>,
) {
let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
err.span_label(span, "cannot resolve opaque type");
// Find the owner that declared this `impl Trait` type.
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let mut prev_hir_id = hir_id;
let mut hir_id = tcx.hir().get_parent_node(hir_id);
while let Some(node) = tcx.hir().find(hir_id) {
match node {
hir::Node::Local(hir::Local {
pat,
init: None,
ty: Some(ty),
source: hir::LocalSource::Normal,
..
}) => {
err.span_label(pat.span, "this binding might not have a concrete type");
err.span_suggestion_verbose(
ty.span.shrink_to_hi(),
"set the binding to a value for a concrete type to be resolved",
" = /* value */".to_string(),
Applicability::HasPlaceholders,
);
}
hir::Node::Local(hir::Local {
init: Some(expr),
source: hir::LocalSource::Normal,
..
}) => {
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let typeck_results =
tcx.typeck(tcx.hir().local_def_id(tcx.hir().get_parent_item(hir_id)));
if let Some(ty) = typeck_results.node_type_opt(expr.hir_id) {
err.span_label(
expr.span,
&format!(
"this is of type `{}`, which doesn't constrain \
`{}` enough to arrive to a concrete type",
ty, partially_expanded_type
),
);
}
}
_ => {}
}
if prev_hir_id == hir_id {
break;
}
prev_hir_id = hir_id;
hir_id = tcx.hir().get_parent_node(hir_id);
}
err.emit();
}
// Forbid defining intrinsics in Rust code,
// as they must always be defined by the compiler.
fn fn_maybe_err(tcx: TyCtxt<'_>, sp: Span, abi: Abi) {

View file

@ -521,8 +521,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
let mut skip_add = false;
if let ty::Opaque(definition_ty_def_id, _substs) = *definition_ty.kind() {
if let hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias = opaque_defn.origin
{
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 {:?} {:?}",

View file

@ -356,9 +356,6 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
let substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
tcx.mk_adt(def, substs)
}
ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::Binding, .. }) => {
let_position_impl_trait_type(tcx, def_id)
}
ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => {
find_opaque_ty_constraints(tcx, def_id)
}
@ -696,60 +693,6 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
}
}
/// Retrieve the inferred concrete type for let position impl trait.
///
/// This is different to other kinds of impl trait because:
///
/// 1. We know which function contains the defining use (the function that
/// contains the let statement)
/// 2. We do not currently allow (free) lifetimes in the return type. `let`
/// statements in some statically unreachable code are removed from the MIR
/// by the time we borrow check, and it's not clear how we should handle
/// those.
fn let_position_impl_trait_type(tcx: TyCtxt<'_>, opaque_ty_id: LocalDefId) -> Ty<'_> {
let scope = tcx.hir().get_defining_scope(tcx.hir().local_def_id_to_hir_id(opaque_ty_id));
let scope_def_id = tcx.hir().local_def_id(scope);
let opaque_ty_def_id = opaque_ty_id.to_def_id();
let owner_typeck_results = tcx.typeck(scope_def_id);
let concrete_ty = owner_typeck_results
.concrete_opaque_types
.get_by(|(key, _)| key.def_id == opaque_ty_def_id)
.map(|concrete_ty| *concrete_ty)
.unwrap_or_else(|| {
tcx.sess.delay_span_bug(
DUMMY_SP,
&format!(
"owner {:?} has no opaque type for {:?} in its typeck results",
scope_def_id, opaque_ty_id
),
);
if let Some(ErrorReported) = owner_typeck_results.tainted_by_errors {
// Some error in the owner fn prevented us from populating the
// `concrete_opaque_types` table.
tcx.ty_error()
} else {
// 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(
opaque_ty_def_id,
InternalSubsts::identity_for_item(tcx, opaque_ty_def_id),
)
}
});
debug!("concrete_ty = {:?}", concrete_ty);
if concrete_ty.has_erased_regions() {
// FIXME(impl_trait_in_bindings) Handle this case.
tcx.sess.span_fatal(
tcx.hir().span(tcx.hir().local_def_id_to_hir_id(opaque_ty_id)),
"lifetimes in impl Trait types in bindings are not currently supported",
);
}
concrete_ty
}
fn infer_placeholder_type<'a>(
tcx: TyCtxt<'a>,
def_id: LocalDefId,