1
Fork 0

Introduce dyn_star feature flag

The primary purpose of this commit is to introduce the
dyn_star flag so we can begin experimenting with implementation.

In order to have something to do in the feature gate test, we also add
parser support for `dyn* Trait` objects. These are currently treated
just like `dyn Trait` objects, but this will change in the future.

Note that for now `dyn* Trait` is experimental syntax to enable
implementing some of the machinery needed for async fn in dyn traits
without fully supporting the feature.
This commit is contained in:
Eric Holk 2022-04-07 18:06:53 -07:00
parent fa6ee93752
commit eff35e59c6
8 changed files with 63 additions and 3 deletions

View file

@ -2072,6 +2072,7 @@ impl TyKind {
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)] #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum TraitObjectSyntax { pub enum TraitObjectSyntax {
Dyn, Dyn,
DynStar,
None, None,
} }

View file

@ -19,6 +19,7 @@ use rustc_session::lint::builtin::{
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY, DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
}; };
use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
use rustc_session::parse::feature_err;
use rustc_session::Session; use rustc_session::Session;
use rustc_span::source_map::Spanned; use rustc_span::source_map::Spanned;
use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::symbol::{kw, sym, Ident};
@ -753,7 +754,19 @@ impl<'a> AstValidator<'a> {
self.maybe_lint_missing_abi(sig_span, ty.id); self.maybe_lint_missing_abi(sig_span, ty.id);
} }
} }
TyKind::TraitObject(ref bounds, ..) => { TyKind::TraitObject(ref bounds, syntax, ..) => {
if syntax == TraitObjectSyntax::DynStar
&& !self.session.features_untracked().dyn_star
{
feature_err(
&self.session.parse_sess,
sym::dyn_star,
ty.span,
"dyn* trait objects are unstable",
)
.emit();
}
let mut any_lifetime_bounds = false; let mut any_lifetime_bounds = false;
for bound in bounds { for bound in bounds {
if let GenericBound::Outlives(ref lifetime) = *bound { if let GenericBound::Outlives(ref lifetime) = *bound {

View file

@ -380,6 +380,8 @@ declare_features! (
(active, doc_cfg_hide, "1.57.0", Some(43781), None), (active, doc_cfg_hide, "1.57.0", Some(43781), None),
/// Allows `#[doc(masked)]`. /// Allows `#[doc(masked)]`.
(active, doc_masked, "1.21.0", Some(44027), None), (active, doc_masked, "1.21.0", Some(44027), None),
/// Allows `dyn* Trait` objects.
(active, dyn_star, "1.65.0", Some(91611), None),
/// Allows `X..Y` patterns. /// Allows `X..Y` patterns.
(active, exclusive_range_pattern, "1.11.0", Some(37854), None), (active, exclusive_range_pattern, "1.11.0", Some(37854), None),
/// Allows exhaustive pattern matching on types that contain uninhabited types. /// Allows exhaustive pattern matching on types that contain uninhabited types.

View file

@ -567,7 +567,8 @@ impl<'a> Parser<'a> {
self.check_keyword(kw::Dyn) self.check_keyword(kw::Dyn)
&& (!self.token.uninterpolated_span().rust_2015() && (!self.token.uninterpolated_span().rust_2015()
|| self.look_ahead(1, |t| { || self.look_ahead(1, |t| {
t.can_begin_bound() && !can_continue_type_after_non_fn_ident(t) (t.can_begin_bound() || t.kind == TokenKind::BinOp(token::Star))
&& !can_continue_type_after_non_fn_ident(t)
})) }))
} }
@ -576,10 +577,20 @@ impl<'a> Parser<'a> {
/// Note that this does *not* parse bare trait objects. /// Note that this does *not* parse bare trait objects.
fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> { fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
self.bump(); // `dyn` self.bump(); // `dyn`
// parse dyn* types
let dyn_star = matches!(self.token.kind, TokenKind::BinOp(token::Star));
let syntax = if dyn_star {
self.bump(); // `*`
TraitObjectSyntax::DynStar
} else {
TraitObjectSyntax::Dyn
};
// Always parse bounds greedily for better error recovery. // Always parse bounds greedily for better error recovery.
let bounds = self.parse_generic_bounds(None)?; let bounds = self.parse_generic_bounds(None)?;
*impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus); *impl_dyn_multi = bounds.len() > 1 || self.prev_token.kind == TokenKind::BinOp(token::Plus);
Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn)) Ok(TyKind::TraitObject(bounds, syntax))
} }
/// Parses a type starting with a path. /// Parses a type starting with a path.

View file

@ -649,6 +649,7 @@ symbols! {
dropck_parametricity, dropck_parametricity,
dylib, dylib,
dyn_metadata, dyn_metadata,
dyn_star,
dyn_trait, dyn_trait,
e, e,
edition_macro_pats, edition_macro_pats,

View file

@ -0,0 +1,9 @@
// Feature gate test for dyn_star
/// dyn* is not necessarily the final surface syntax (if we have one at all),
/// but for now we will support it to aid in writing tests independently.
pub fn dyn_star_parameter(_: &dyn* Send) {
//~^ dyn* trait objects are unstable
}
fn main() {}

View file

@ -0,0 +1,12 @@
error[E0658]: dyn* trait objects are unstable
--> $DIR/feature-gate-dyn_star.rs:5:31
|
LL | pub fn dyn_star_parameter(_: &dyn* Send) {
| ^^^^^^^^^
|
= note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
= help: add `#![feature(dyn_star)]` to the crate attributes to enable
error: aborting due to previous error
For more information about this error, try `rustc --explain E0658`.

View file

@ -0,0 +1,11 @@
// Make sure we can parse the `dyn* Trait` syntax
//
// check-pass
#![feature(dyn_star)]
pub fn dyn_star_parameter(_: &dyn* Send) {
}
fn main() {}