Skip to content

Commit

Permalink
Auto merge of #82898 - oli-obk:tait_🧊, r=nikomatsakis
Browse files Browse the repository at this point in the history
Add a `min_type_alias_impl_trait` feature gate

This new feature gate only permits type alias impl trait to be constrained by function and trait method return types. All other possible constraining sites like const/static types, closure return types and binding types are now forbidden and gated under the `type_alias_impl_trait` and `impl_trait_in_bindings` feature gates (which are both marked as incomplete, as they have various ways to ICE the compiler or cause query cycles where they shouldn't).

r? `@nikomatsakis`

This is best reviewed commit-by-commit
  • Loading branch information
bors committed Mar 16, 2021
2 parents 4c10c84 + e675941 commit 195ad48
Show file tree
Hide file tree
Showing 362 changed files with 5,447 additions and 686 deletions.
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(..), .. }) |
// 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

0 comments on commit 195ad48

Please sign in to comment.