Skip to content

Commit 195ad48

Browse files
committed
Auto merge of #82898 - oli-obk:tait_🧊, r=nikomatsakis
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
2 parents 4c10c84 + e675941 commit 195ad48

File tree

362 files changed

+5447
-686
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

362 files changed

+5447
-686
lines changed

compiler/rustc_ast_lowering/src/item.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
342342
ty,
343343
ImplTraitContext::OtherOpaqueTy {
344344
capturable_lifetimes: &mut FxHashSet::default(),
345-
origin: hir::OpaqueTyOrigin::Misc,
345+
origin: hir::OpaqueTyOrigin::TyAlias,
346346
},
347347
);
348348
let generics = self.lower_generics(gen, ImplTraitContext::disallowed());
@@ -918,7 +918,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
918918
ty,
919919
ImplTraitContext::OtherOpaqueTy {
920920
capturable_lifetimes: &mut FxHashSet::default(),
921-
origin: hir::OpaqueTyOrigin::Misc,
921+
origin: hir::OpaqueTyOrigin::TyAlias,
922922
},
923923
);
924924
hir::ImplItemKind::TyAlias(ty)

compiler/rustc_ast_passes/src/feature_gate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ impl<'a> PostExpansionVisitor<'a> {
279279
if let ast::TyKind::ImplTrait(..) = ty.kind {
280280
gate_feature_post!(
281281
&self.vis,
282-
type_alias_impl_trait,
282+
min_type_alias_impl_trait,
283283
ty.span,
284284
"`impl Trait` in type aliases is unstable"
285285
);

compiler/rustc_feature/src/active.rs

+4
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,9 @@ declare_features! (
638638
/// Allows `pub` on `macro_rules` items.
639639
(active, pub_macro_rules, "1.52.0", Some(78855), None),
640640

641+
/// Allows the use of type alias impl trait in function return positions
642+
(active, min_type_alias_impl_trait, "1.52.0", Some(63063), None),
643+
641644
/// Allows associated types in inherent impls.
642645
(active, inherent_associated_types, "1.52.0", Some(8995), None),
643646

@@ -670,6 +673,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
670673
sym::capture_disjoint_fields,
671674
sym::const_generics_defaults,
672675
sym::inherent_associated_types,
676+
sym::type_alias_impl_trait,
673677
];
674678

675679
/// Some features are not allowed to be used together at the same time, if

compiler/rustc_feature/src/removed.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ declare_features! (
106106
Some("subsumed by `.await` syntax")),
107107
/// Allows defining `existential type`s.
108108
(removed, existential_type, "1.38.0", Some(63063), None,
109-
Some("removed in favor of `#![feature(type_alias_impl_trait)]`")),
109+
Some("removed in favor of `#![feature(min_type_alias_impl_trait)]`")),
110110
/// Allows using the macros:
111111
/// + `__diagnostic_used`
112112
/// + `__register_diagnostic`

compiler/rustc_hir/src/hir.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2291,7 +2291,9 @@ pub enum OpaqueTyOrigin {
22912291
AsyncFn,
22922292
/// `let _: impl Trait = ...`
22932293
Binding,
2294-
/// Impl trait in type aliases, consts, statics, bounds.
2294+
/// type aliases: `type Foo = impl Trait;`
2295+
TyAlias,
2296+
/// Impl trait consts, statics, bounds.
22952297
Misc,
22962298
}
22972299

compiler/rustc_mir/src/borrow_check/region_infer/opaque_types.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
4747
/// Calling `universal_upper_bound` for such a region gives `fr_fn_body`,
4848
/// which has no `external_name` in which case we use `'empty` as the
4949
/// region to pass to `infer_opaque_definition_from_instantiation`.
50+
#[instrument(skip(self, infcx))]
5051
pub(in crate::borrow_check) fn infer_opaque_types(
5152
&self,
5253
infcx: &InferCtxt<'_, 'tcx>,
@@ -56,10 +57,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
5657
opaque_ty_decls
5758
.into_iter()
5859
.map(|(opaque_def_id, ty::ResolvedOpaqueTy { concrete_type, substs })| {
59-
debug!(
60-
"infer_opaque_types(concrete_type = {:?}, substs = {:?})",
61-
concrete_type, substs
62-
);
60+
debug!(?concrete_type, ?substs);
6361

6462
let mut subst_regions = vec![self.universal_regions.fr_static];
6563
let universal_substs =
@@ -110,10 +108,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
110108
}
111109
});
112110

113-
debug!(
114-
"infer_opaque_types(universal_concrete_type = {:?}, universal_substs = {:?})",
115-
universal_concrete_type, universal_substs
116-
);
111+
debug!(?universal_concrete_type, ?universal_substs);
117112

118113
let remapped_type = infcx.infer_opaque_definition_from_instantiation(
119114
opaque_def_id,

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -736,6 +736,7 @@ symbols! {
736736
min_const_generics,
737737
min_const_unsafe_fn,
738738
min_specialization,
739+
min_type_alias_impl_trait,
739740
minnumf32,
740741
minnumf64,
741742
mips_target_feature,

compiler/rustc_trait_selection/src/opaque_types.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
422422
}
423423
// These opaque type inherit all lifetime parameters from their
424424
// parent, so we have to check them all.
425-
hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc => 0,
425+
hir::OpaqueTyOrigin::Binding
426+
| hir::OpaqueTyOrigin::TyAlias
427+
| hir::OpaqueTyOrigin::Misc => 0,
426428
};
427429

428430
let span = tcx.def_span(def_id);
@@ -581,6 +583,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
581583
// Otherwise, generate the label we'll use in the error message.
582584
hir::OpaqueTyOrigin::Binding
583585
| hir::OpaqueTyOrigin::FnReturn
586+
| hir::OpaqueTyOrigin::TyAlias
584587
| hir::OpaqueTyOrigin::Misc => "impl Trait",
585588
};
586589
let msg = format!("ambiguous lifetime bound in `{}`", context_name);

compiler/rustc_typeck/src/check/check.rs

+65-3
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,69 @@ pub(super) fn check_fn<'a, 'tcx>(
8787

8888
let declared_ret_ty = fn_sig.output();
8989

90-
let revealed_ret_ty =
91-
fcx.instantiate_opaque_types_from_value(fn_id, declared_ret_ty, decl.output.span());
90+
let feature = match tcx.hir().get(fn_id) {
91+
// TAIT usage in function return position.
92+
// Example:
93+
//
94+
// ```rust
95+
// type Foo = impl Debug;
96+
// fn bar() -> Foo { 42 }
97+
// ```
98+
Node::Item(hir::Item { kind: ItemKind::Fn(..), .. }) |
99+
// TAIT usage in associated function return position.
100+
//
101+
// Example with a free type alias:
102+
//
103+
// ```rust
104+
// type Foo = impl Debug;
105+
// impl SomeTrait for SomeType {
106+
// fn bar() -> Foo { 42 }
107+
// }
108+
// ```
109+
//
110+
// Example with an associated TAIT:
111+
//
112+
// ```rust
113+
// impl SomeTrait for SomeType {
114+
// type Foo = impl Debug;
115+
// fn bar() -> Self::Foo { 42 }
116+
// }
117+
// ```
118+
Node::ImplItem(hir::ImplItem {
119+
kind: hir::ImplItemKind::Fn(..), ..
120+
}) => None,
121+
// Forbid TAIT in trait declarations for now.
122+
// Examples:
123+
//
124+
// ```rust
125+
// type Foo = impl Debug;
126+
// trait Bar {
127+
// fn bar() -> Foo;
128+
// }
129+
// trait Bop {
130+
// type Bop: PartialEq<Foo>;
131+
// }
132+
// ```
133+
Node::TraitItem(hir::TraitItem {
134+
kind: hir::TraitItemKind::Fn(..),
135+
..
136+
}) |
137+
// Forbid TAIT in closure return position for now.
138+
// Example:
139+
//
140+
// ```rust
141+
// type Foo = impl Debug;
142+
// let x = |y| -> Foo { 42 + y };
143+
// ```
144+
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => Some(sym::type_alias_impl_trait),
145+
node => bug!("Item being checked wasn't a function/closure: {:?}", node),
146+
};
147+
let revealed_ret_ty = fcx.instantiate_opaque_types_from_value(
148+
fn_id,
149+
declared_ret_ty,
150+
decl.output.span(),
151+
feature,
152+
);
92153
debug!("check_fn: declared_ret_ty: {}, revealed_ret_ty: {}", declared_ret_ty, revealed_ret_ty);
93154
fcx.ret_coercion = Some(RefCell::new(CoerceMany::new(revealed_ret_ty)));
94155
fcx.ret_type_span = Some(decl.output.span());
@@ -659,7 +720,8 @@ fn check_opaque_meets_bounds<'tcx>(
659720
// Checked when type checking the function containing them.
660721
hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => return,
661722
// Can have different predicates to their defining use
662-
hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc => {}
723+
hir::OpaqueTyOrigin::Binding | hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias => {
724+
}
663725
}
664726

665727
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);

compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ use rustc_middle::ty::{
2626
self, AdtKind, CanonicalUserType, DefIdTree, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
2727
Ty, UserType,
2828
};
29-
use rustc_session::lint;
30-
use rustc_span::hygiene::DesugaringKind;
29+
use rustc_session::{lint, parse::feature_err};
3130
use rustc_span::source_map::{original_sp, DUMMY_SP};
3231
use rustc_span::symbol::{kw, sym, Ident};
3332
use rustc_span::{self, BytePos, MultiSpan, Span};
33+
use rustc_span::{hygiene::DesugaringKind, Symbol};
3434
use rustc_trait_selection::infer::InferCtxtExt as _;
3535
use rustc_trait_selection::opaque_types::InferCtxtExt as _;
3636
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
@@ -362,6 +362,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
362362
parent_id: hir::HirId,
363363
value: T,
364364
value_span: Span,
365+
feature: Option<Symbol>,
365366
) -> T {
366367
let parent_def_id = self.tcx.hir().local_def_id(parent_id);
367368
debug!(
@@ -380,7 +381,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
380381

381382
let mut opaque_types = self.opaque_types.borrow_mut();
382383
let mut opaque_types_vars = self.opaque_types_vars.borrow_mut();
384+
383385
for (ty, decl) in opaque_type_map {
386+
if let Some(feature) = feature {
387+
if let hir::OpaqueTyOrigin::TyAlias = decl.origin {
388+
if !self.tcx.features().enabled(feature) {
389+
feature_err(
390+
&self.tcx.sess.parse_sess,
391+
feature,
392+
value_span,
393+
"type alias impl trait is not permitted here",
394+
)
395+
.emit();
396+
}
397+
}
398+
}
384399
let _ = opaque_types.insert(ty, decl);
385400
let _ = opaque_types_vars.insert(decl.concrete_ty, decl.opaque_type);
386401
}

compiler/rustc_typeck/src/check/gather_locals.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
44
use rustc_hir::PatKind;
55
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
66
use rustc_middle::ty::Ty;
7-
use rustc_span::Span;
7+
use rustc_span::{sym, Span};
88
use rustc_trait_selection::traits;
99
use std::mem;
1010

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

61-
let revealed_ty = if self.fcx.tcx.features().impl_trait_in_bindings {
62-
self.fcx.instantiate_opaque_types_from_value(self.parent_id, o_ty, ty.span)
63-
} else {
64-
o_ty
65-
};
61+
let revealed_ty = self.fcx.instantiate_opaque_types_from_value(
62+
self.parent_id,
63+
o_ty,
64+
ty.span,
65+
Some(sym::impl_trait_in_bindings),
66+
);
6667

6768
let c_ty =
6869
self.fcx.inh.infcx.canonicalize_user_type_annotation(UserType::Ty(revealed_ty));

compiler/rustc_typeck/src/check/mod.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ use rustc_middle::ty::{self, RegionKind, Ty, TyCtxt, UserType};
121121
use rustc_session::config;
122122
use rustc_session::parse::feature_err;
123123
use rustc_session::Session;
124-
use rustc_span::source_map::DUMMY_SP;
125124
use rustc_span::symbol::{kw, Ident};
126125
use rustc_span::{self, BytePos, MultiSpan, Span};
126+
use rustc_span::{source_map::DUMMY_SP, sym};
127127
use rustc_target::abi::VariantIdx;
128128
use rustc_target::spec::abi::Abi;
129129
use rustc_trait_selection::traits;
@@ -547,11 +547,12 @@ fn typeck_with_fallback<'tcx>(
547547
let expected_type = fcx.normalize_associated_types_in(body.value.span, expected_type);
548548
fcx.require_type_is_sized(expected_type, body.value.span, traits::ConstSized);
549549

550-
let revealed_ty = if tcx.features().impl_trait_in_bindings {
551-
fcx.instantiate_opaque_types_from_value(id, expected_type, body.value.span)
552-
} else {
553-
expected_type
554-
};
550+
let revealed_ty = fcx.instantiate_opaque_types_from_value(
551+
id,
552+
expected_type,
553+
body.value.span,
554+
Some(sym::impl_trait_in_bindings),
555+
);
555556

556557
// Gather locals in statics (because of block expressions).
557558
GatherLocalsVisitor::new(&fcx, id).visit_body(body);

compiler/rustc_typeck/src/check/writeback.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
497497
let mut skip_add = false;
498498

499499
if let ty::Opaque(defin_ty_def_id, _substs) = *definition_ty.kind() {
500-
if let hir::OpaqueTyOrigin::Misc = opaque_defn.origin {
500+
if let hir::OpaqueTyOrigin::Misc | hir::OpaqueTyOrigin::TyAlias = opaque_defn.origin
501+
{
501502
if def_id == defin_ty_def_id {
502503
debug!(
503504
"skipping adding concrete definition for opaque type {:?} {:?}",

library/alloc/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,8 @@
142142
#![feature(alloc_layout_extra)]
143143
#![feature(trusted_random_access)]
144144
#![feature(try_trait)]
145-
#![feature(type_alias_impl_trait)]
145+
#![cfg_attr(bootstrap, feature(type_alias_impl_trait))]
146+
#![cfg_attr(not(bootstrap), feature(min_type_alias_impl_trait))]
146147
#![feature(associated_type_bounds)]
147148
#![feature(slice_group_by)]
148149
#![feature(decl_macro)]

src/test/rustdoc-ui/error-in-impl-trait/trait-alias-closure.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// check-pass
2-
#![feature(type_alias_impl_trait)]
2+
#![feature(min_type_alias_impl_trait)]
33

44
pub trait ValidTrait {}
55
type ImplTrait = impl ValidTrait;

src/test/rustdoc-ui/error-in-impl-trait/trait-alias.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// check-pass
2-
#![feature(type_alias_impl_trait)]
2+
#![feature(min_type_alias_impl_trait)]
33

44
pub trait ValidTrait {}
55
type ImplTrait = impl ValidTrait;

src/test/rustdoc/auxiliary/issue-73061.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//edition:2018
22

3-
#![feature(type_alias_impl_trait)]
3+
#![feature(min_type_alias_impl_trait)]
44

55
pub trait Foo {
66
type X: std::future::Future<Output = ()>;

src/test/rustdoc/impl-trait-alias.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(type_alias_impl_trait)]
1+
#![feature(min_type_alias_impl_trait)]
22

33
trait MyTrait {}
44
impl MyTrait for i32 {}

src/test/rustdoc/return-impl-trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(type_alias_impl_trait)]
1+
#![feature(min_type_alias_impl_trait)]
22

33
pub trait Backend {}
44

0 commit comments

Comments
 (0)