Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a min_type_alias_impl_trait feature gate #82898

Merged
merged 11 commits into from
Mar 16, 2021
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ty,
ImplTraitContext::OtherOpaqueTy {
capturable_lifetimes: &mut FxHashSet::default(),
origin: hir::OpaqueTyOrigin::Misc,
origin: hir::OpaqueTyOrigin::TyAlias,
},
);
let generics = self.lower_generics(gen, ImplTraitContext::disallowed());
Expand Down Expand Up @@ -918,7 +918,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ty,
ImplTraitContext::OtherOpaqueTy {
capturable_lifetimes: &mut FxHashSet::default(),
origin: hir::OpaqueTyOrigin::Misc,
origin: hir::OpaqueTyOrigin::TyAlias,
},
);
hir::ImplItemKind::TyAlias(ty)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ impl<'a> PostExpansionVisitor<'a> {
if let ast::TyKind::ImplTrait(..) = ty.kind {
gate_feature_post!(
&self.vis,
type_alias_impl_trait,
min_type_alias_impl_trait,
ty.span,
"`impl Trait` in type aliases is unstable"
);
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,9 @@ declare_features! (
/// Allows `pub` on `macro_rules` items.
(active, pub_macro_rules, "1.52.0", Some(78855), None),

/// Allows the use of type alias impl trait in function return positions
(active, min_type_alias_impl_trait, "1.52.0", Some(63063), None),

/// Allows associated types in inherent impls.
(active, inherent_associated_types, "1.52.0", Some(8995), None),

Expand Down Expand Up @@ -670,6 +673,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
sym::capture_disjoint_fields,
sym::const_generics_defaults,
sym::inherent_associated_types,
sym::type_alias_impl_trait,
];

/// Some features are not allowed to be used together at the same time, if
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_feature/src/removed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ declare_features! (
Some("subsumed by `.await` syntax")),
/// Allows defining `existential type`s.
(removed, existential_type, "1.38.0", Some(63063), None,
Some("removed in favor of `#![feature(type_alias_impl_trait)]`")),
Some("removed in favor of `#![feature(min_type_alias_impl_trait)]`")),
/// Allows using the macros:
/// + `__diagnostic_used`
/// + `__register_diagnostic`
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2291,7 +2291,9 @@ pub enum OpaqueTyOrigin {
AsyncFn,
/// `let _: impl Trait = ...`
Binding,
/// Impl trait in type aliases, consts, statics, bounds.
/// type aliases: `type Foo = impl Trait;`
TyAlias,
/// Impl trait consts, statics, bounds.
Misc,
}

Expand Down
11 changes: 3 additions & 8 deletions compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// Calling `universal_upper_bound` for such a region gives `fr_fn_body`,
/// which has no `external_name` in which case we use `'empty` as the
/// region to pass to `infer_opaque_definition_from_instantiation`.
#[instrument(skip(self, infcx))]
pub(in crate::borrow_check) fn infer_opaque_types(
&self,
infcx: &InferCtxt<'_, 'tcx>,
Expand All @@ -56,10 +57,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
opaque_ty_decls
.into_iter()
.map(|(opaque_def_id, ty::ResolvedOpaqueTy { concrete_type, substs })| {
debug!(
"infer_opaque_types(concrete_type = {:?}, substs = {:?})",
concrete_type, substs
);
debug!(?concrete_type, ?substs);

let mut subst_regions = vec![self.universal_regions.fr_static];
let universal_substs =
Expand Down Expand Up @@ -110,10 +108,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
});

debug!(
"infer_opaque_types(universal_concrete_type = {:?}, universal_substs = {:?})",
universal_concrete_type, universal_substs
);
debug!(?universal_concrete_type, ?universal_substs);

let remapped_type = infcx.infer_opaque_definition_from_instantiation(
opaque_def_id,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,7 @@ symbols! {
min_const_generics,
min_const_unsafe_fn,
min_specialization,
min_type_alias_impl_trait,
minnumf32,
minnumf64,
mips_target_feature,
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_trait_selection/src/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
}
// These opaque type inherit all lifetime parameters from their
// parent, so we have to check them all.
hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc => 0,
hir::OpaqueTyOrigin::Binding
| hir::OpaqueTyOrigin::TyAlias
| hir::OpaqueTyOrigin::Misc => 0,
};

let span = tcx.def_span(def_id);
Expand Down Expand Up @@ -581,6 +583,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
// Otherwise, generate the label we'll use in the error message.
hir::OpaqueTyOrigin::Binding
| hir::OpaqueTyOrigin::FnReturn
| hir::OpaqueTyOrigin::TyAlias
| hir::OpaqueTyOrigin::Misc => "impl Trait",
};
let msg = format!("ambiguous lifetime bound in `{}`", context_name);
Expand Down
68 changes: 65 additions & 3 deletions compiler/rustc_typeck/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,69 @@ pub(super) fn check_fn<'a, 'tcx>(

let declared_ret_ty = fn_sig.output();

let revealed_ret_ty =
fcx.instantiate_opaque_types_from_value(fn_id, declared_ret_ty, decl.output.span());
let feature = match tcx.hir().get(fn_id) {
// TAIT usage in function return position.
// Example:
//
// ```rust
// type Foo = impl Debug;
// fn bar() -> Foo { 42 }
// ```
Node::Item(hir::Item { kind: ItemKind::Fn(..), .. }) |
oli-obk marked this conversation as resolved.
Show resolved Hide resolved
// TAIT usage in associated function return position.
//
// Example with a free type alias:
//
// ```rust
// type Foo = impl Debug;
// impl SomeTrait for SomeType {
// fn bar() -> Foo { 42 }
// }
// ```
//
// Example with an associated TAIT:
//
// ```rust
// impl SomeTrait for SomeType {
// type Foo = impl Debug;
// fn bar() -> Self::Foo { 42 }
// }
// ```
Node::ImplItem(hir::ImplItem {
kind: hir::ImplItemKind::Fn(..), ..
}) => None,
// Forbid TAIT in trait declarations for now.
// Examples:
//
// ```rust
// type Foo = impl Debug;
// trait Bar {
// fn bar() -> Foo;
// }
// trait Bop {
// type Bop: PartialEq<Foo>;
// }
// ```
Node::TraitItem(hir::TraitItem {
kind: hir::TraitItemKind::Fn(..),
..
}) |
// Forbid TAIT in closure return position for now.
// Example:
//
// ```rust
// type Foo = impl Debug;
// let x = |y| -> Foo { 42 + y };
// ```
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => Some(sym::type_alias_impl_trait),
node => bug!("Item being checked wasn't a function/closure: {:?}", node),
};
let revealed_ret_ty = fcx.instantiate_opaque_types_from_value(
fn_id,
declared_ret_ty,
decl.output.span(),
feature,
);
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());
Expand Down Expand Up @@ -659,7 +720,8 @@ 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::Binding | hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias => {
}
}

let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
Expand Down
19 changes: 17 additions & 2 deletions compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ use rustc_middle::ty::{
self, AdtKind, CanonicalUserType, DefIdTree, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
Ty, UserType,
};
use rustc_session::lint;
use rustc_span::hygiene::DesugaringKind;
use rustc_session::{lint, parse::feature_err};
use rustc_span::source_map::{original_sp, DUMMY_SP};
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{self, BytePos, MultiSpan, Span};
use rustc_span::{hygiene::DesugaringKind, Symbol};
use rustc_trait_selection::infer::InferCtxtExt as _;
use rustc_trait_selection::opaque_types::InferCtxtExt as _;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
Expand Down Expand Up @@ -362,6 +362,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
parent_id: hir::HirId,
value: T,
value_span: Span,
feature: Option<Symbol>,
) -> T {
let parent_def_id = self.tcx.hir().local_def_id(parent_id);
debug!(
Expand All @@ -380,7 +381,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

let mut opaque_types = self.opaque_types.borrow_mut();
let mut opaque_types_vars = self.opaque_types_vars.borrow_mut();

for (ty, decl) in opaque_type_map {
if let Some(feature) = feature {
if let hir::OpaqueTyOrigin::TyAlias = decl.origin {
if !self.tcx.features().enabled(feature) {
feature_err(
&self.tcx.sess.parse_sess,
feature,
value_span,
"type alias impl trait is not permitted here",
)
.emit();
}
}
}
let _ = opaque_types.insert(ty, decl);
let _ = opaque_types_vars.insert(decl.concrete_ty, decl.opaque_type);
}
Expand Down
13 changes: 7 additions & 6 deletions compiler/rustc_typeck/src/check/gather_locals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ 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::Span;
use rustc_span::{sym, Span};
use rustc_trait_selection::traits;
use std::mem;

Expand Down Expand Up @@ -58,11 +58,12 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
Some(ref ty) => {
let o_ty = self.fcx.to_ty(&ty);

let revealed_ty = if self.fcx.tcx.features().impl_trait_in_bindings {
self.fcx.instantiate_opaque_types_from_value(self.parent_id, o_ty, ty.span)
} else {
o_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));
Expand Down
13 changes: 7 additions & 6 deletions compiler/rustc_typeck/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ use rustc_middle::ty::{self, RegionKind, 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;
Expand Down Expand Up @@ -547,11 +547,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 = if tcx.features().impl_trait_in_bindings {
fcx.instantiate_opaque_types_from_value(id, expected_type, body.value.span)
} else {
expected_type
};
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);
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_typeck/src/check/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
let mut skip_add = false;

if let ty::Opaque(defin_ty_def_id, _substs) = *definition_ty.kind() {
if let hir::OpaqueTyOrigin::Misc = opaque_defn.origin {
if let hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias = opaque_defn.origin
{
if def_id == defin_ty_def_id {
debug!(
"skipping adding concrete definition for opaque type {:?} {:?}",
Expand Down
3 changes: 2 additions & 1 deletion library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@
#![feature(alloc_layout_extra)]
#![feature(trusted_random_access)]
#![feature(try_trait)]
#![feature(type_alias_impl_trait)]
#![cfg_attr(bootstrap, feature(type_alias_impl_trait))]
#![cfg_attr(not(bootstrap), feature(min_type_alias_impl_trait))]
#![feature(associated_type_bounds)]
#![feature(slice_group_by)]
#![feature(decl_macro)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// check-pass
#![feature(type_alias_impl_trait)]
#![feature(min_type_alias_impl_trait)]

pub trait ValidTrait {}
type ImplTrait = impl ValidTrait;
Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// check-pass
#![feature(type_alias_impl_trait)]
#![feature(min_type_alias_impl_trait)]

pub trait ValidTrait {}
type ImplTrait = impl ValidTrait;
Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc/auxiliary/issue-73061.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//edition:2018

#![feature(type_alias_impl_trait)]
#![feature(min_type_alias_impl_trait)]

pub trait Foo {
type X: std::future::Future<Output = ()>;
Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc/impl-trait-alias.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(type_alias_impl_trait)]
#![feature(min_type_alias_impl_trait)]

trait MyTrait {}
impl MyTrait for i32 {}
Expand Down
2 changes: 1 addition & 1 deletion src/test/rustdoc/return-impl-trait.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(type_alias_impl_trait)]
#![feature(min_type_alias_impl_trait)]

pub trait Backend {}

Expand Down
Loading