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 type_ascribe! macro as placeholder syntax for type ascription #104614

Merged
merged 3 commits into from
Dec 2, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_builtin_macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -45,6 +45,7 @@ mod log_syntax;
mod source_util;
mod test;
mod trace_macros;
mod type_ascribe;
mod util;

pub mod asm;
@@ -92,6 +93,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
unreachable: edition_panic::expand_unreachable,
stringify: source_util::expand_stringify,
trace_macros: trace_macros::expand_trace_macros,
type_ascribe: type_ascribe::expand_type_ascribe,
}

register_attr! {
35 changes: 35 additions & 0 deletions compiler/rustc_builtin_macros/src/type_ascribe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use rustc_ast::ptr::P;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{token, Expr, ExprKind, Ty};
use rustc_errors::PResult;
use rustc_expand::base::{self, DummyResult, ExtCtxt, MacEager};
use rustc_span::Span;

pub fn expand_type_ascribe(
cx: &mut ExtCtxt<'_>,
span: Span,
tts: TokenStream,
) -> Box<dyn base::MacResult + 'static> {
let (expr, ty) = match parse_ascribe(cx, tts) {
Ok(parsed) => parsed,
Err(mut err) => {
err.emit();
return DummyResult::any(span);
}
};

let asc_expr = cx.expr(span, ExprKind::Type(expr, ty));

return MacEager::expr(asc_expr);
}

fn parse_ascribe<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Expr>, P<Ty>)> {
let mut parser = cx.new_parser_from_tts(stream);

let expr = parser.parse_expr()?;
parser.expect(&token::Comma)?;

let ty = parser.parse_ty()?;

Ok((expr, ty))
}
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -1485,6 +1485,7 @@ symbols! {
ty,
type_alias_enum_variants,
type_alias_impl_trait,
type_ascribe,
type_ascription,
type_changing_struct_update,
type_id,
12 changes: 12 additions & 0 deletions library/core/src/macros/mod.rs
Original file line number Diff line number Diff line change
@@ -1546,6 +1546,18 @@ pub(crate) mod builtin {
/* compiler built-in */
}

/// Unstable placeholder for type ascription.
#[rustc_builtin_macro]
#[unstable(
feature = "type_ascription",
issue = "23416",
reason = "placeholder syntax for type ascription"
)]
#[cfg(not(bootstrap))]
pub macro type_ascribe($expr:expr, $ty:ty) {
/* compiler built-in */
}

/// Unstable implementation detail of the `rustc` compiler, do not use.
#[rustc_builtin_macro]
#[stable(feature = "rust1", since = "1.0.0")]
8 changes: 8 additions & 0 deletions library/core/src/prelude/v1.rs
Original file line number Diff line number Diff line change
@@ -98,3 +98,11 @@ pub use crate::macros::builtin::cfg_accessible;
reason = "`cfg_eval` is a recently implemented feature"
)]
pub use crate::macros::builtin::cfg_eval;

#[unstable(
feature = "type_ascription",
issue = "23416",
reason = "placeholder syntax for type ascription"
)]
#[cfg(not(bootstrap))]
pub use crate::macros::builtin::type_ascribe;
9 changes: 9 additions & 0 deletions library/std/src/prelude/v1.rs
Original file line number Diff line number Diff line change
@@ -85,6 +85,15 @@ pub use core::prelude::v1::cfg_accessible;
)]
pub use core::prelude::v1::cfg_eval;

// Do not `doc(no_inline)` either.
#[unstable(
feature = "type_ascription",
issue = "23416",
reason = "placeholder syntax for type ascription"
)]
#[cfg(not(bootstrap))]
pub use core::prelude::v1::type_ascribe;

// The file so far is equivalent to src/libcore/prelude/v1.rs,
// and below to src/liballoc/prelude.rs.
// Those files are duplicated rather than using glob imports
8 changes: 5 additions & 3 deletions src/test/ui/associated-consts/issue-93835.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#![feature(type_ascription)]

fn e() {
p:a<p:p<e=6>>
//~^ ERROR comparison operators
type_ascribe!(p, a<p:p<e=6>>);
//~^ ERROR cannot find type `a` in this scope
//~| ERROR cannot find value
//~| ERROR associated const equality
//~| ERROR associated const equality
//~| ERROR cannot find trait `p` in this scope
//~| ERROR associated type bounds
}

65 changes: 20 additions & 45 deletions src/test/ui/associated-consts/issue-93835.stderr
Original file line number Diff line number Diff line change
@@ -1,65 +1,40 @@
error: comparison operators cannot be chained
--> $DIR/issue-93835.rs:2:8
|
LL | fn e() {
| - while parsing this struct
LL | p:a<p:p<e=6>>
| ^ ^
|
= help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
= help: or use `(...)` if you meant to specify fn arguments

error[E0425]: cannot find value `p` in this scope
--> $DIR/issue-93835.rs:2:5
|
LL | p:a<p:p<e=6>>
| ^ not found in this scope
|
help: you might have meant to write a `struct` literal
|
LL ~ fn e() { SomeStruct {
LL | p:a<p:p<e=6>>
...
LL |
LL ~ }}
--> $DIR/issue-93835.rs:4:19
|
help: maybe you meant to write a path separator here
|
LL | p::a<p:p<e=6>>
| ~~
help: maybe you meant to write an assignment here
|
LL | let p:a<p:p<e=6>>
| ~~~~~
LL | type_ascribe!(p, a<p:p<e=6>>);
| ^ not found in this scope

error[E0658]: associated const equality is incomplete
--> $DIR/issue-93835.rs:2:13
error[E0412]: cannot find type `a` in this scope
--> $DIR/issue-93835.rs:4:22
|
LL | p:a<p:p<e=6>>
| ^^^
LL | type_ascribe!(p, a<p:p<e=6>>);
| ^ not found in this scope

error[E0405]: cannot find trait `p` in this scope
--> $DIR/issue-93835.rs:4:26
|
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
= help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
LL | type_ascribe!(p, a<p:p<e=6>>);
| ^ not found in this scope

error[E0658]: associated const equality is incomplete
--> $DIR/issue-93835.rs:2:13
--> $DIR/issue-93835.rs:4:28
|
LL | p:a<p:p<e=6>>
| ^^^
LL | type_ascribe!(p, a<p:p<e=6>>);
| ^^^
|
= note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
= help: add `#![feature(associated_const_equality)]` to the crate attributes to enable

error[E0658]: associated type bounds are unstable
--> $DIR/issue-93835.rs:2:9
--> $DIR/issue-93835.rs:4:24
|
LL | p:a<p:p<e=6>>
| ^^^^^^^^
LL | type_ascribe!(p, a<p:p<e=6>>);
| ^^^^^^^^
|
= note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
= help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable

error: aborting due to 5 previous errors

Some errors have detailed explanations: E0425, E0658.
For more information about an error, try `rustc --explain E0425`.
Some errors have detailed explanations: E0405, E0412, E0425, E0658.
For more information about an error, try `rustc --explain E0405`.
4 changes: 3 additions & 1 deletion src/test/ui/closures/issue-90871.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#![feature(type_ascription)]

fn main() {
2: n([u8; || 1])
type_ascribe!(2, n([u8; || 1]))
//~^ ERROR cannot find type `n` in this scope
//~| ERROR mismatched types
}
23 changes: 14 additions & 9 deletions src/test/ui/closures/issue-90871.stderr
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
error[E0412]: cannot find type `n` in this scope
--> $DIR/issue-90871.rs:2:8
--> $DIR/issue-90871.rs:4:22
|
LL | 2: n([u8; || 1])
| ^ expecting a type here because of type ascription
LL | type_ascribe!(2, n([u8; || 1]))
| ^ help: a trait with a similar name exists: `Fn`
|
::: $SRC_DIR/core/src/ops/function.rs:LL:COL
|
LL | pub trait Fn<Args: Tuple>: FnMut<Args> {
| -------------------------------------- similarly named trait `Fn` defined here

error[E0308]: mismatched types
--> $DIR/issue-90871.rs:2:15
--> $DIR/issue-90871.rs:4:29
|
LL | 2: n([u8; || 1])
| ^^^^ expected `usize`, found closure
LL | type_ascribe!(2, n([u8; || 1]))
| ^^^^ expected `usize`, found closure
|
= note: expected type `usize`
found closure `[closure@$DIR/issue-90871.rs:2:15: 2:17]`
found closure `[closure@$DIR/issue-90871.rs:4:29: 4:31]`
help: use parentheses to call this closure
|
LL | 2: n([u8; (|| 1)()])
| + +++
LL | type_ascribe!(2, n([u8; (|| 1)()]))
| + +++

error: aborting due to 2 previous errors

32 changes: 16 additions & 16 deletions src/test/ui/coercion/coerce-expect-unsized-ascribed.rs
Original file line number Diff line number Diff line change
@@ -6,27 +6,27 @@
use std::fmt::Debug;

pub fn main() {
let _ = box { [1, 2, 3] }: Box<[i32]>; //~ ERROR mismatched types
let _ = box if true { [1, 2, 3] } else { [1, 3, 4] }: Box<[i32]>; //~ ERROR mismatched types
let _ = box match true { true => [1, 2, 3], false => [1, 3, 4] }: Box<[i32]>;
let _ = type_ascribe!(box { [1, 2, 3] }, Box<[i32]>); //~ ERROR mismatched types
let _ = type_ascribe!(box if true { [1, 2, 3] } else { [1, 3, 4] }, Box<[i32]>); //~ ERROR mismatched types
let _ = type_ascribe!(box match true { true => [1, 2, 3], false => [1, 3, 4] }, Box<[i32]>);
//~^ ERROR mismatched types
let _ = box { |x| (x as u8) }: Box<dyn Fn(i32) -> _>; //~ ERROR mismatched types
let _ = box if true { false } else { true }: Box<dyn Debug>; //~ ERROR mismatched types
let _ = box match true { true => 'a', false => 'b' }: Box<dyn Debug>; //~ ERROR mismatched types
let _ = type_ascribe!(box { |x| (x as u8) }, Box<dyn Fn(i32) -> _>); //~ ERROR mismatched types
let _ = type_ascribe!(box if true { false } else { true }, Box<dyn Debug>); //~ ERROR mismatched types
let _ = type_ascribe!(box match true { true => 'a', false => 'b' }, Box<dyn Debug>); //~ ERROR mismatched types

let _ = &{ [1, 2, 3] }: &[i32]; //~ ERROR mismatched types
let _ = &if true { [1, 2, 3] } else { [1, 3, 4] }: &[i32]; //~ ERROR mismatched types
let _ = &match true { true => [1, 2, 3], false => [1, 3, 4] }: &[i32];
let _ = type_ascribe!(&{ [1, 2, 3] }, &[i32]); //~ ERROR mismatched types
let _ = type_ascribe!(&if true { [1, 2, 3] } else { [1, 3, 4] }, &[i32]); //~ ERROR mismatched types
let _ = type_ascribe!(&match true { true => [1, 2, 3], false => [1, 3, 4] }, &[i32]);
//~^ ERROR mismatched types
let _ = &{ |x| (x as u8) }: &dyn Fn(i32) -> _; //~ ERROR mismatched types
let _ = &if true { false } else { true }: &dyn Debug; //~ ERROR mismatched types
let _ = &match true { true => 'a', false => 'b' }: &dyn Debug; //~ ERROR mismatched types
let _ = type_ascribe!(&{ |x| (x as u8) }, &dyn Fn(i32) -> _); //~ ERROR mismatched types
let _ = type_ascribe!(&if true { false } else { true }, &dyn Debug); //~ ERROR mismatched types
let _ = type_ascribe!(&match true { true => 'a', false => 'b' }, &dyn Debug); //~ ERROR mismatched types

let _ = Box::new([1, 2, 3]): Box<[i32]>; //~ ERROR mismatched types
let _ = Box::new(|x| (x as u8)): Box<dyn Fn(i32) -> _>; //~ ERROR mismatched types
let _ = type_ascribe!(Box::new([1, 2, 3]), Box<[i32]>); //~ ERROR mismatched types
let _ = type_ascribe!(Box::new(|x| (x as u8)), Box<dyn Fn(i32) -> _>); //~ ERROR mismatched types

let _ = vec![
let _ = type_ascribe!(vec![
Box::new(|x| (x as u8)),
box |x| (x as i16 as u8),
]: Vec<Box<dyn Fn(i32) -> _>>;
], Vec<Box<dyn Fn(i32) -> _>>);
}
Loading