Auto merge of #33376 - Manishearth:rollup, r=Manishearth
Rollup of 14 pull requests - Successful merges: #33277, #33294, #33314, #33322, #33333, #33338, #33339, #33340, #33343, #33357, #33363, #33365, #33371, #33372 - Failed merges:
This commit is contained in:
commit
7a0ccc458f
|
@ -8,7 +8,7 @@ we’ll talk about Cargo, Rust’s build system and package manager.
|
||||||
|
|
||||||
The first step to using Rust is to install it. Generally speaking, you’ll need
|
The first step to using Rust is to install it. Generally speaking, you’ll need
|
||||||
an Internet connection to run the commands in this section, as we’ll be
|
an Internet connection to run the commands in this section, as we’ll be
|
||||||
downloading Rust from the internet.
|
downloading Rust from the Internet.
|
||||||
|
|
||||||
We’ll be showing off a number of commands using a terminal, and those lines all
|
We’ll be showing off a number of commands using a terminal, and those lines all
|
||||||
start with `$`. We don't need to type in the `$`s, they are there to indicate
|
start with `$`. We don't need to type in the `$`s, they are there to indicate
|
||||||
|
@ -399,13 +399,13 @@ Let’s convert the Hello World program to Cargo. To Cargo-fy a project, you nee
|
||||||
to do three things:
|
to do three things:
|
||||||
|
|
||||||
1. Put your source file in the right directory.
|
1. Put your source file in the right directory.
|
||||||
2. Get rid of the old executable (`main.exe` on Windows, `main` everywhere else)
|
2. Get rid of the old executable (`main.exe` on Windows, `main` everywhere
|
||||||
and make a new one.
|
else).
|
||||||
3. Make a Cargo configuration file.
|
3. Make a Cargo configuration file.
|
||||||
|
|
||||||
Let's get started!
|
Let's get started!
|
||||||
|
|
||||||
### Creating a new Executable and Source Directory
|
### Creating a Source Directory and Removing the Old Executable
|
||||||
|
|
||||||
First, go back to your terminal, move to your *hello_world* directory, and
|
First, go back to your terminal, move to your *hello_world* directory, and
|
||||||
enter the following commands:
|
enter the following commands:
|
||||||
|
|
|
@ -333,7 +333,7 @@
|
||||||
//! precision := count | '*'
|
//! precision := count | '*'
|
||||||
//! type := identifier | ''
|
//! type := identifier | ''
|
||||||
//! count := parameter | integer
|
//! count := parameter | integer
|
||||||
//! parameter := integer '$'
|
//! parameter := argument '$'
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! # Formatting Parameters
|
//! # Formatting Parameters
|
||||||
|
@ -403,11 +403,12 @@
|
||||||
//! println!("Hello {:5}!", "x");
|
//! println!("Hello {:5}!", "x");
|
||||||
//! println!("Hello {:1$}!", "x", 5);
|
//! println!("Hello {:1$}!", "x", 5);
|
||||||
//! println!("Hello {1:0$}!", 5, "x");
|
//! println!("Hello {1:0$}!", 5, "x");
|
||||||
|
//! println!("Hello {:width$}!", "x", width = 5);
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! Referring to an argument with the dollar syntax does not affect the "next
|
//! Referring to an argument with the dollar syntax does not affect the "next
|
||||||
//! argument" counter, so it's usually a good idea to refer to all arguments by
|
//! argument" counter, so it's usually a good idea to refer to arguments by
|
||||||
//! their position explicitly.
|
//! position, or use named arguments.
|
||||||
//!
|
//!
|
||||||
//! ## Precision
|
//! ## Precision
|
||||||
//!
|
//!
|
||||||
|
@ -426,7 +427,7 @@
|
||||||
//!
|
//!
|
||||||
//! the integer `N` itself is the precision.
|
//! the integer `N` itself is the precision.
|
||||||
//!
|
//!
|
||||||
//! 2. An integer followed by dollar sign `.N$`:
|
//! 2. An integer or name followed by dollar sign `.N$`:
|
||||||
//!
|
//!
|
||||||
//! use format *argument* `N` (which must be a `usize`) as the precision.
|
//! use format *argument* `N` (which must be a `usize`) as the precision.
|
||||||
//!
|
//!
|
||||||
|
@ -456,6 +457,10 @@
|
||||||
//! // Hello {next arg (x)} is {arg 2 (0.01) with precision
|
//! // Hello {next arg (x)} is {arg 2 (0.01) with precision
|
||||||
//! // specified in its predecessor (5)}
|
//! // specified in its predecessor (5)}
|
||||||
//! println!("Hello {} is {2:.*}", "x", 5, 0.01);
|
//! println!("Hello {} is {2:.*}", "x", 5, 0.01);
|
||||||
|
//!
|
||||||
|
//! // Hello {next arg (x)} is {arg "number" (0.01) with precision specified
|
||||||
|
//! // in arg "prec" (5)}
|
||||||
|
//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! All print the same thing:
|
//! All print the same thing:
|
||||||
|
|
|
@ -110,6 +110,7 @@ pub use intrinsics::transmute;
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn forget<T>(t: T) {
|
pub fn forget<T>(t: T) {
|
||||||
unsafe { intrinsics::forget(t) }
|
unsafe { intrinsics::forget(t) }
|
||||||
|
|
|
@ -314,6 +314,82 @@ let c = &i; // still ok!
|
||||||
```
|
```
|
||||||
"##,
|
"##,
|
||||||
|
|
||||||
|
E0501: r##"
|
||||||
|
This error indicates that a mutable variable is being used while it is still
|
||||||
|
captured by a closure. Because the closure has borrowed the variable, it is not
|
||||||
|
available for use until the closure goes out of scope.
|
||||||
|
|
||||||
|
Note that a capture will either move or borrow a variable, but in this
|
||||||
|
situation, the closure is borrowing the variable. Take a look at
|
||||||
|
http://rustbyexample.com/fn/closures/capture.html for more information about
|
||||||
|
capturing.
|
||||||
|
|
||||||
|
Example of erroneous code:
|
||||||
|
|
||||||
|
```compile_fail
|
||||||
|
fn inside_closure(x: &mut i32) {
|
||||||
|
// Actions which require unique access
|
||||||
|
}
|
||||||
|
|
||||||
|
fn outside_closure(x: &mut i32) {
|
||||||
|
// Actions which require unique access
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(a: &mut i32) {
|
||||||
|
let bar = || {
|
||||||
|
inside_closure(a)
|
||||||
|
};
|
||||||
|
outside_closure(a); // error: cannot borrow `*a` as mutable because previous
|
||||||
|
// closure requires unique access.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To fix this error, you can place the closure in its own scope:
|
||||||
|
|
||||||
|
```
|
||||||
|
fn inside_closure(x: &mut i32) {}
|
||||||
|
fn outside_closure(x: &mut i32) {}
|
||||||
|
|
||||||
|
fn foo(a: &mut i32) {
|
||||||
|
{
|
||||||
|
let bar = || {
|
||||||
|
inside_closure(a)
|
||||||
|
};
|
||||||
|
} // borrow on `a` ends.
|
||||||
|
outside_closure(a); // ok!
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or you can pass the variable as a parameter to the closure:
|
||||||
|
|
||||||
|
```
|
||||||
|
fn inside_closure(x: &mut i32) {}
|
||||||
|
fn outside_closure(x: &mut i32) {}
|
||||||
|
|
||||||
|
fn foo(a: &mut i32) {
|
||||||
|
let bar = |s: &mut i32| {
|
||||||
|
inside_closure(s)
|
||||||
|
};
|
||||||
|
outside_closure(a);
|
||||||
|
bar(a);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
It may be possible to define the closure later:
|
||||||
|
|
||||||
|
```
|
||||||
|
fn inside_closure(x: &mut i32) {}
|
||||||
|
fn outside_closure(x: &mut i32) {}
|
||||||
|
|
||||||
|
fn foo(a: &mut i32) {
|
||||||
|
outside_closure(a);
|
||||||
|
let bar = || {
|
||||||
|
inside_closure(a)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
"##,
|
||||||
|
|
||||||
E0507: r##"
|
E0507: r##"
|
||||||
You tried to move out of a value which was borrowed. Erroneous code example:
|
You tried to move out of a value which was borrowed. Erroneous code example:
|
||||||
|
|
||||||
|
@ -436,7 +512,6 @@ register_diagnostics! {
|
||||||
E0388, // {} in a static location
|
E0388, // {} in a static location
|
||||||
E0389, // {} in a `&` reference
|
E0389, // {} in a `&` reference
|
||||||
E0500, // closure requires unique access to `..` but .. is already borrowed
|
E0500, // closure requires unique access to `..` but .. is already borrowed
|
||||||
E0501, // cannot borrow `..`.. as .. because previous closure requires unique access
|
|
||||||
E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ...
|
E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ...
|
||||||
E0503, // cannot use `..` because it was mutably borrowed
|
E0503, // cannot use `..` because it was mutably borrowed
|
||||||
E0504, // cannot move `..` into closure because it is borrowed
|
E0504, // cannot move `..` into closure because it is borrowed
|
||||||
|
|
|
@ -377,13 +377,6 @@ pub enum ErrKind {
|
||||||
NotOn(ConstVal),
|
NotOn(ConstVal),
|
||||||
CallOn(ConstVal),
|
CallOn(ConstVal),
|
||||||
|
|
||||||
NegateWithOverflow(i64),
|
|
||||||
AddiWithOverflow(i64, i64),
|
|
||||||
SubiWithOverflow(i64, i64),
|
|
||||||
MuliWithOverflow(i64, i64),
|
|
||||||
AdduWithOverflow(u64, u64),
|
|
||||||
SubuWithOverflow(u64, u64),
|
|
||||||
MuluWithOverflow(u64, u64),
|
|
||||||
DivideByZero,
|
DivideByZero,
|
||||||
DivideWithOverflow,
|
DivideWithOverflow,
|
||||||
ModuloByZero,
|
ModuloByZero,
|
||||||
|
@ -415,6 +408,7 @@ pub enum ErrKind {
|
||||||
TypeMismatch(String, ConstInt),
|
TypeMismatch(String, ConstInt),
|
||||||
BadType(ConstVal),
|
BadType(ConstVal),
|
||||||
ErroneousReferencedConstant(Box<ConstEvalErr>),
|
ErroneousReferencedConstant(Box<ConstEvalErr>),
|
||||||
|
CharCast(ConstInt),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ConstMathErr> for ErrKind {
|
impl From<ConstMathErr> for ErrKind {
|
||||||
|
@ -439,13 +433,6 @@ impl ConstEvalErr {
|
||||||
NotOn(ref const_val) => format!("not on {}", const_val.description()).into_cow(),
|
NotOn(ref const_val) => format!("not on {}", const_val.description()).into_cow(),
|
||||||
CallOn(ref const_val) => format!("call on {}", const_val.description()).into_cow(),
|
CallOn(ref const_val) => format!("call on {}", const_val.description()).into_cow(),
|
||||||
|
|
||||||
NegateWithOverflow(..) => "attempted to negate with overflow".into_cow(),
|
|
||||||
AddiWithOverflow(..) => "attempted to add with overflow".into_cow(),
|
|
||||||
SubiWithOverflow(..) => "attempted to sub with overflow".into_cow(),
|
|
||||||
MuliWithOverflow(..) => "attempted to mul with overflow".into_cow(),
|
|
||||||
AdduWithOverflow(..) => "attempted to add with overflow".into_cow(),
|
|
||||||
SubuWithOverflow(..) => "attempted to sub with overflow".into_cow(),
|
|
||||||
MuluWithOverflow(..) => "attempted to mul with overflow".into_cow(),
|
|
||||||
DivideByZero => "attempted to divide by zero".into_cow(),
|
DivideByZero => "attempted to divide by zero".into_cow(),
|
||||||
DivideWithOverflow => "attempted to divide with overflow".into_cow(),
|
DivideWithOverflow => "attempted to divide with overflow".into_cow(),
|
||||||
ModuloByZero => "attempted remainder with a divisor of zero".into_cow(),
|
ModuloByZero => "attempted remainder with a divisor of zero".into_cow(),
|
||||||
|
@ -482,6 +469,9 @@ impl ConstEvalErr {
|
||||||
},
|
},
|
||||||
BadType(ref i) => format!("value of wrong type: {:?}", i).into_cow(),
|
BadType(ref i) => format!("value of wrong type: {:?}", i).into_cow(),
|
||||||
ErroneousReferencedConstant(_) => "could not evaluate referenced constant".into_cow(),
|
ErroneousReferencedConstant(_) => "could not evaluate referenced constant".into_cow(),
|
||||||
|
CharCast(ref got) => {
|
||||||
|
format!("only `u8` can be cast as `char`, not `{}`", got.description()).into_cow()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -824,7 +814,10 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||||
debug!("const call({:?})", call_args);
|
debug!("const call({:?})", call_args);
|
||||||
eval_const_expr_partial(tcx, &result, ty_hint, Some(&call_args))?
|
eval_const_expr_partial(tcx, &result, ty_hint, Some(&call_args))?
|
||||||
},
|
},
|
||||||
hir::ExprLit(ref lit) => lit_to_const(&lit.node, tcx, ety, lit.span)?,
|
hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ety, lit.span) {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(err) => signal!(e, err),
|
||||||
|
},
|
||||||
hir::ExprBlock(ref block) => {
|
hir::ExprBlock(ref block) => {
|
||||||
match block.expr {
|
match block.expr {
|
||||||
Some(ref expr) => eval_const_expr_partial(tcx, &expr, ty_hint, fn_args)?,
|
Some(ref expr) => eval_const_expr_partial(tcx, &expr, ty_hint, fn_args)?,
|
||||||
|
@ -930,7 +923,10 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
|
||||||
};
|
};
|
||||||
|
|
||||||
match (ety.map(|t| &t.sty), result) {
|
match (ety.map(|t| &t.sty), result) {
|
||||||
(Some(ref ty_hint), Integral(i)) => Ok(Integral(infer(i, tcx, ty_hint, e.span)?)),
|
(Some(ref ty_hint), Integral(i)) => match infer(i, tcx, ty_hint) {
|
||||||
|
Ok(inferred) => Ok(Integral(inferred)),
|
||||||
|
Err(err) => signal!(e, err),
|
||||||
|
},
|
||||||
(_, result) => Ok(result),
|
(_, result) => Ok(result),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -939,15 +935,9 @@ fn infer<'tcx>(
|
||||||
i: ConstInt,
|
i: ConstInt,
|
||||||
tcx: &TyCtxt<'tcx>,
|
tcx: &TyCtxt<'tcx>,
|
||||||
ty_hint: &ty::TypeVariants<'tcx>,
|
ty_hint: &ty::TypeVariants<'tcx>,
|
||||||
span: Span
|
) -> Result<ConstInt, ErrKind> {
|
||||||
) -> Result<ConstInt, ConstEvalErr> {
|
|
||||||
use syntax::ast::*;
|
use syntax::ast::*;
|
||||||
|
|
||||||
let err = |e| ConstEvalErr {
|
|
||||||
span: span,
|
|
||||||
kind: e,
|
|
||||||
};
|
|
||||||
|
|
||||||
match (ty_hint, i) {
|
match (ty_hint, i) {
|
||||||
(&ty::TyInt(IntTy::I8), result @ I8(_)) => Ok(result),
|
(&ty::TyInt(IntTy::I8), result @ I8(_)) => Ok(result),
|
||||||
(&ty::TyInt(IntTy::I16), result @ I16(_)) => Ok(result),
|
(&ty::TyInt(IntTy::I16), result @ I16(_)) => Ok(result),
|
||||||
|
@ -993,17 +983,17 @@ fn infer<'tcx>(
|
||||||
Err(_) => Ok(Usize(ConstUsize::Us32(i as u32))),
|
Err(_) => Ok(Usize(ConstUsize::Us32(i as u32))),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(&ty::TyUint(_), InferSigned(_)) => Err(err(IntermediateUnsignedNegative)),
|
(&ty::TyUint(_), InferSigned(_)) => Err(IntermediateUnsignedNegative),
|
||||||
|
|
||||||
(&ty::TyInt(ity), i) => Err(err(TypeMismatch(ity.to_string(), i))),
|
(&ty::TyInt(ity), i) => Err(TypeMismatch(ity.to_string(), i)),
|
||||||
(&ty::TyUint(ity), i) => Err(err(TypeMismatch(ity.to_string(), i))),
|
(&ty::TyUint(ity), i) => Err(TypeMismatch(ity.to_string(), i)),
|
||||||
|
|
||||||
(&ty::TyEnum(ref adt, _), i) => {
|
(&ty::TyEnum(ref adt, _), i) => {
|
||||||
let hints = tcx.lookup_repr_hints(adt.did);
|
let hints = tcx.lookup_repr_hints(adt.did);
|
||||||
let int_ty = tcx.enum_repr_type(hints.iter().next());
|
let int_ty = tcx.enum_repr_type(hints.iter().next());
|
||||||
infer(i, tcx, &int_ty.to_ty(tcx).sty, span)
|
infer(i, tcx, &int_ty.to_ty(tcx).sty)
|
||||||
},
|
},
|
||||||
(_, i) => Err(err(BadType(ConstVal::Integral(i)))),
|
(_, i) => Err(BadType(ConstVal::Integral(i))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1089,23 +1079,22 @@ fn cast_const_int<'tcx>(tcx: &TyCtxt<'tcx>, val: ConstInt, ty: ty::Ty) -> CastRe
|
||||||
Err(_) => Ok(Integral(Usize(ConstUsize::Us32(v as u32)))),
|
Err(_) => Ok(Integral(Usize(ConstUsize::Us32(v as u32)))),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ty::TyFloat(ast::FloatTy::F64) if val.is_negative() => {
|
ty::TyFloat(ast::FloatTy::F64) => match val.erase_type() {
|
||||||
// FIXME: this could probably be prettier
|
Infer(u) => Ok(Float(u as f64)),
|
||||||
// there's no easy way to turn an `Infer` into a f64
|
InferSigned(i) => Ok(Float(i as f64)),
|
||||||
let val = (-val).map_err(Math)?;
|
_ => bug!("ConstInt::erase_type returned something other than Infer/InferSigned"),
|
||||||
let val = val.to_u64().unwrap() as f64;
|
|
||||||
let val = -val;
|
|
||||||
Ok(Float(val))
|
|
||||||
},
|
},
|
||||||
ty::TyFloat(ast::FloatTy::F64) => Ok(Float(val.to_u64().unwrap() as f64)),
|
ty::TyFloat(ast::FloatTy::F32) => match val.erase_type() {
|
||||||
ty::TyFloat(ast::FloatTy::F32) if val.is_negative() => {
|
Infer(u) => Ok(Float(u as f32 as f64)),
|
||||||
let val = (-val).map_err(Math)?;
|
InferSigned(i) => Ok(Float(i as f32 as f64)),
|
||||||
let val = val.to_u64().unwrap() as f32;
|
_ => bug!("ConstInt::erase_type returned something other than Infer/InferSigned"),
|
||||||
let val = -val;
|
|
||||||
Ok(Float(val as f64))
|
|
||||||
},
|
},
|
||||||
ty::TyFloat(ast::FloatTy::F32) => Ok(Float(val.to_u64().unwrap() as f32 as f64)),
|
|
||||||
ty::TyRawPtr(_) => Err(ErrKind::UnimplementedConstVal("casting an address to a raw ptr")),
|
ty::TyRawPtr(_) => Err(ErrKind::UnimplementedConstVal("casting an address to a raw ptr")),
|
||||||
|
ty::TyChar => match infer(val, tcx, &ty::TyUint(ast::UintTy::U8)) {
|
||||||
|
Ok(U8(u)) => Ok(Char(u as char)),
|
||||||
|
// can only occur before typeck, typeck blocks `T as char` for `T` != `u8`
|
||||||
|
_ => Err(CharCast(val)),
|
||||||
|
},
|
||||||
_ => Err(CannotCast),
|
_ => Err(CannotCast),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1136,7 +1125,7 @@ fn lit_to_const<'tcx>(lit: &ast::LitKind,
|
||||||
tcx: &TyCtxt<'tcx>,
|
tcx: &TyCtxt<'tcx>,
|
||||||
ty_hint: Option<Ty<'tcx>>,
|
ty_hint: Option<Ty<'tcx>>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<ConstVal, ConstEvalErr> {
|
) -> Result<ConstVal, ErrKind> {
|
||||||
use syntax::ast::*;
|
use syntax::ast::*;
|
||||||
use syntax::ast::LitIntType::*;
|
use syntax::ast::LitIntType::*;
|
||||||
match *lit {
|
match *lit {
|
||||||
|
@ -1144,28 +1133,28 @@ fn lit_to_const<'tcx>(lit: &ast::LitKind,
|
||||||
LitKind::ByteStr(ref data) => Ok(ByteStr(data.clone())),
|
LitKind::ByteStr(ref data) => Ok(ByteStr(data.clone())),
|
||||||
LitKind::Byte(n) => Ok(Integral(U8(n))),
|
LitKind::Byte(n) => Ok(Integral(U8(n))),
|
||||||
LitKind::Int(n, Signed(ity)) => {
|
LitKind::Int(n, Signed(ity)) => {
|
||||||
infer(InferSigned(n as i64), tcx, &ty::TyInt(ity), span).map(Integral)
|
infer(InferSigned(n as i64), tcx, &ty::TyInt(ity)).map(Integral)
|
||||||
},
|
},
|
||||||
|
|
||||||
LitKind::Int(n, Unsuffixed) => {
|
LitKind::Int(n, Unsuffixed) => {
|
||||||
match ty_hint.map(|t| &t.sty) {
|
match ty_hint.map(|t| &t.sty) {
|
||||||
Some(&ty::TyInt(ity)) => {
|
Some(&ty::TyInt(ity)) => {
|
||||||
infer(InferSigned(n as i64), tcx, &ty::TyInt(ity), span).map(Integral)
|
infer(InferSigned(n as i64), tcx, &ty::TyInt(ity)).map(Integral)
|
||||||
},
|
},
|
||||||
Some(&ty::TyUint(uty)) => {
|
Some(&ty::TyUint(uty)) => {
|
||||||
infer(Infer(n), tcx, &ty::TyUint(uty), span).map(Integral)
|
infer(Infer(n), tcx, &ty::TyUint(uty)).map(Integral)
|
||||||
},
|
},
|
||||||
None => Ok(Integral(Infer(n))),
|
None => Ok(Integral(Infer(n))),
|
||||||
Some(&ty::TyEnum(ref adt, _)) => {
|
Some(&ty::TyEnum(ref adt, _)) => {
|
||||||
let hints = tcx.lookup_repr_hints(adt.did);
|
let hints = tcx.lookup_repr_hints(adt.did);
|
||||||
let int_ty = tcx.enum_repr_type(hints.iter().next());
|
let int_ty = tcx.enum_repr_type(hints.iter().next());
|
||||||
infer(Infer(n), tcx, &int_ty.to_ty(tcx).sty, span).map(Integral)
|
infer(Infer(n), tcx, &int_ty.to_ty(tcx).sty).map(Integral)
|
||||||
},
|
},
|
||||||
Some(ty_hint) => bug!("bad ty_hint: {:?}, {:?}", ty_hint, lit),
|
Some(ty_hint) => bug!("bad ty_hint: {:?}, {:?}", ty_hint, lit),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
LitKind::Int(n, Unsigned(ity)) => {
|
LitKind::Int(n, Unsigned(ity)) => {
|
||||||
infer(Infer(n), tcx, &ty::TyUint(ity), span).map(Integral)
|
infer(Infer(n), tcx, &ty::TyUint(ity)).map(Integral)
|
||||||
},
|
},
|
||||||
|
|
||||||
LitKind::Float(ref n, _) |
|
LitKind::Float(ref n, _) |
|
||||||
|
|
|
@ -147,7 +147,7 @@ enum ResolutionError<'a> {
|
||||||
/// error E0416: identifier is bound more than once in the same pattern
|
/// error E0416: identifier is bound more than once in the same pattern
|
||||||
IdentifierBoundMoreThanOnceInSamePattern(&'a str),
|
IdentifierBoundMoreThanOnceInSamePattern(&'a str),
|
||||||
/// error E0417: static variables cannot be referenced in a pattern
|
/// error E0417: static variables cannot be referenced in a pattern
|
||||||
StaticVariableReference,
|
StaticVariableReference(DefId, Option<Name>),
|
||||||
/// error E0418: is not an enum variant, struct or const
|
/// error E0418: is not an enum variant, struct or const
|
||||||
NotAnEnumVariantStructOrConst(&'a str),
|
NotAnEnumVariantStructOrConst(&'a str),
|
||||||
/// error E0419: unresolved enum variant, struct or const
|
/// error E0419: unresolved enum variant, struct or const
|
||||||
|
@ -352,12 +352,24 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>,
|
||||||
"identifier `{}` is bound more than once in the same pattern",
|
"identifier `{}` is bound more than once in the same pattern",
|
||||||
identifier)
|
identifier)
|
||||||
}
|
}
|
||||||
ResolutionError::StaticVariableReference => {
|
ResolutionError::StaticVariableReference(did, name) => {
|
||||||
struct_span_err!(resolver.session,
|
let mut err = struct_span_err!(resolver.session,
|
||||||
span,
|
span,
|
||||||
E0417,
|
E0417,
|
||||||
"static variables cannot be referenced in a pattern, use a \
|
"static variables cannot be referenced in a \
|
||||||
`const` instead")
|
pattern, use a `const` instead");
|
||||||
|
if let Some(sp) = resolver.ast_map.span_if_local(did) {
|
||||||
|
err.span_note(sp, "static variable defined here");
|
||||||
|
}
|
||||||
|
if let Some(name) = name {
|
||||||
|
if let Some(binding) = resolver.current_module
|
||||||
|
.resolve_name_in_lexical_scope(name, ValueNS) {
|
||||||
|
if binding.is_import() {
|
||||||
|
err.span_note(binding.span, "static variable imported here");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err
|
||||||
}
|
}
|
||||||
ResolutionError::NotAnEnumVariantStructOrConst(name) => {
|
ResolutionError::NotAnEnumVariantStructOrConst(name) => {
|
||||||
struct_span_err!(resolver.session,
|
struct_span_err!(resolver.session,
|
||||||
|
@ -2313,10 +2325,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
Def::Variant(..) | Def::Const(..) => {
|
Def::Variant(..) | Def::Const(..) => {
|
||||||
self.record_def(pattern.id, path_res);
|
self.record_def(pattern.id, path_res);
|
||||||
}
|
}
|
||||||
Def::Static(..) => {
|
Def::Static(did, _) => {
|
||||||
resolve_error(&self,
|
resolve_error(&self,
|
||||||
path.span,
|
path.span,
|
||||||
ResolutionError::StaticVariableReference);
|
ResolutionError::StaticVariableReference(
|
||||||
|
did, None));
|
||||||
self.record_def(pattern.id, err_path_resolution());
|
self.record_def(pattern.id, err_path_resolution());
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -2456,8 +2469,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||||
Some(def @ Def::Const(..)) | Some(def @ Def::AssociatedConst(..)) => {
|
Some(def @ Def::Const(..)) | Some(def @ Def::AssociatedConst(..)) => {
|
||||||
FoundConst(def, ident.unhygienic_name)
|
FoundConst(def, ident.unhygienic_name)
|
||||||
}
|
}
|
||||||
Some(Def::Static(..)) => {
|
Some(Def::Static(did, _)) => {
|
||||||
resolve_error(self, span, ResolutionError::StaticVariableReference);
|
resolve_error(self, span, ResolutionError::StaticVariableReference(
|
||||||
|
did, Some(ident.unhygienic_name)));
|
||||||
BareIdentifierPatternUnresolved
|
BareIdentifierPatternUnresolved
|
||||||
}
|
}
|
||||||
_ => BareIdentifierPatternUnresolved,
|
_ => BareIdentifierPatternUnresolved,
|
||||||
|
|
|
@ -20,6 +20,7 @@ use rustc::hir;
|
||||||
use rustc::middle::cstore::{self, CrateStore};
|
use rustc::middle::cstore::{self, CrateStore};
|
||||||
use rustc::hir::def::Def;
|
use rustc::hir::def::Def;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
|
use rustc::hir::print as pprust;
|
||||||
use rustc::ty::{self, TyCtxt};
|
use rustc::ty::{self, TyCtxt};
|
||||||
use rustc::ty::subst;
|
use rustc::ty::subst;
|
||||||
use rustc::middle::stability;
|
use rustc::middle::stability;
|
||||||
|
@ -30,7 +31,7 @@ use core::{DocContext, DocAccessLevels};
|
||||||
use doctree;
|
use doctree;
|
||||||
use clean::{self, GetDefId};
|
use clean::{self, GetDefId};
|
||||||
|
|
||||||
use super::{Clean, ToSource};
|
use super::Clean;
|
||||||
|
|
||||||
/// Attempt to inline the definition of a local node id into this AST.
|
/// Attempt to inline the definition of a local node id into this AST.
|
||||||
///
|
///
|
||||||
|
@ -333,8 +334,8 @@ pub fn build_impl(cx: &DocContext,
|
||||||
let did = assoc_const.def_id;
|
let did = assoc_const.def_id;
|
||||||
let type_scheme = tcx.lookup_item_type(did);
|
let type_scheme = tcx.lookup_item_type(did);
|
||||||
let default = if assoc_const.has_value {
|
let default = if assoc_const.has_value {
|
||||||
Some(lookup_const_by_id(tcx, did, None)
|
Some(pprust::expr_to_string(
|
||||||
.unwrap().0.span.to_src(cx))
|
lookup_const_by_id(tcx, did, None).unwrap().0))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -479,8 +480,6 @@ fn build_module(cx: &DocContext, tcx: &TyCtxt,
|
||||||
|
|
||||||
fn build_const(cx: &DocContext, tcx: &TyCtxt,
|
fn build_const(cx: &DocContext, tcx: &TyCtxt,
|
||||||
did: DefId) -> clean::Constant {
|
did: DefId) -> clean::Constant {
|
||||||
use rustc::hir::print as pprust;
|
|
||||||
|
|
||||||
let (expr, ty) = lookup_const_by_id(tcx, did, None).unwrap_or_else(|| {
|
let (expr, ty) = lookup_const_by_id(tcx, did, None).unwrap_or_else(|| {
|
||||||
panic!("expected lookup_const_by_id to succeed for {:?}", did);
|
panic!("expected lookup_const_by_id to succeed for {:?}", did);
|
||||||
});
|
});
|
||||||
|
|
|
@ -39,6 +39,7 @@ use rustc::middle::cstore::{self, CrateStore};
|
||||||
use rustc::middle::privacy::AccessLevels;
|
use rustc::middle::privacy::AccessLevels;
|
||||||
use rustc::hir::def::Def;
|
use rustc::hir::def::Def;
|
||||||
use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
|
use rustc::hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
|
||||||
|
use rustc::hir::print as pprust;
|
||||||
use rustc::ty::subst::{self, ParamSpace, VecPerParamSpace};
|
use rustc::ty::subst::{self, ParamSpace, VecPerParamSpace};
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use rustc::middle::stability;
|
use rustc::middle::stability;
|
||||||
|
@ -1285,8 +1286,7 @@ impl Clean<Item> for hir::TraitItem {
|
||||||
let inner = match self.node {
|
let inner = match self.node {
|
||||||
hir::ConstTraitItem(ref ty, ref default) => {
|
hir::ConstTraitItem(ref ty, ref default) => {
|
||||||
AssociatedConstItem(ty.clean(cx),
|
AssociatedConstItem(ty.clean(cx),
|
||||||
default.as_ref().map(|expr|
|
default.as_ref().map(|e| pprust::expr_to_string(&e)))
|
||||||
expr.span.to_src(cx)))
|
|
||||||
}
|
}
|
||||||
hir::MethodTraitItem(ref sig, Some(_)) => {
|
hir::MethodTraitItem(ref sig, Some(_)) => {
|
||||||
MethodItem(sig.clean(cx))
|
MethodItem(sig.clean(cx))
|
||||||
|
@ -1316,7 +1316,7 @@ impl Clean<Item> for hir::ImplItem {
|
||||||
let inner = match self.node {
|
let inner = match self.node {
|
||||||
hir::ImplItemKind::Const(ref ty, ref expr) => {
|
hir::ImplItemKind::Const(ref ty, ref expr) => {
|
||||||
AssociatedConstItem(ty.clean(cx),
|
AssociatedConstItem(ty.clean(cx),
|
||||||
Some(expr.span.to_src(cx)))
|
Some(pprust::expr_to_string(expr)))
|
||||||
}
|
}
|
||||||
hir::ImplItemKind::Method(ref sig, _) => {
|
hir::ImplItemKind::Method(ref sig, _) => {
|
||||||
MethodItem(sig.clean(cx))
|
MethodItem(sig.clean(cx))
|
||||||
|
@ -1635,8 +1635,8 @@ impl Clean<Type> for hir::Ty {
|
||||||
BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
|
BorrowedRef {lifetime: l.clean(cx), mutability: m.mutbl.clean(cx),
|
||||||
type_: box m.ty.clean(cx)},
|
type_: box m.ty.clean(cx)},
|
||||||
TyVec(ref ty) => Vector(box ty.clean(cx)),
|
TyVec(ref ty) => Vector(box ty.clean(cx)),
|
||||||
TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx),
|
TyFixedLengthVec(ref ty, ref e) =>
|
||||||
e.span.to_src(cx)),
|
FixedVector(box ty.clean(cx), pprust::expr_to_string(e)),
|
||||||
TyTup(ref tys) => Tuple(tys.clean(cx)),
|
TyTup(ref tys) => Tuple(tys.clean(cx)),
|
||||||
TyPath(None, ref p) => {
|
TyPath(None, ref p) => {
|
||||||
resolve_type(cx, p.clean(cx), self.id)
|
resolve_type(cx, p.clean(cx), self.id)
|
||||||
|
@ -2185,7 +2185,7 @@ impl Clean<Item> for doctree::Static {
|
||||||
inner: StaticItem(Static {
|
inner: StaticItem(Static {
|
||||||
type_: self.type_.clean(cx),
|
type_: self.type_.clean(cx),
|
||||||
mutability: self.mutability.clean(cx),
|
mutability: self.mutability.clean(cx),
|
||||||
expr: self.expr.span.to_src(cx),
|
expr: pprust::expr_to_string(&self.expr),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2209,7 +2209,7 @@ impl Clean<Item> for doctree::Constant {
|
||||||
deprecation: self.depr.clean(cx),
|
deprecation: self.depr.clean(cx),
|
||||||
inner: ConstantItem(Constant {
|
inner: ConstantItem(Constant {
|
||||||
type_: self.type_.clean(cx),
|
type_: self.type_.clean(cx),
|
||||||
expr: self.expr.span.to_src(cx),
|
expr: pprust::expr_to_string(&self.expr),
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ use rustc::hir;
|
||||||
use clean;
|
use clean;
|
||||||
use core::DocAccessLevels;
|
use core::DocAccessLevels;
|
||||||
use html::item_type::ItemType;
|
use html::item_type::ItemType;
|
||||||
|
use html::escape::Escape;
|
||||||
use html::render;
|
use html::render;
|
||||||
use html::render::{cache, CURRENT_LOCATION_KEY};
|
use html::render::{cache, CURRENT_LOCATION_KEY};
|
||||||
|
|
||||||
|
@ -496,7 +497,7 @@ impl fmt::Display for clean::Type {
|
||||||
primitive_link(f, clean::PrimitiveType::Array, "[")?;
|
primitive_link(f, clean::PrimitiveType::Array, "[")?;
|
||||||
write!(f, "{}", t)?;
|
write!(f, "{}", t)?;
|
||||||
primitive_link(f, clean::PrimitiveType::Array,
|
primitive_link(f, clean::PrimitiveType::Array,
|
||||||
&format!("; {}]", *s))
|
&format!("; {}]", Escape(s)))
|
||||||
}
|
}
|
||||||
clean::Bottom => f.write_str("!"),
|
clean::Bottom => f.write_str("!"),
|
||||||
clean::RawPointer(m, ref t) => {
|
clean::RawPointer(m, ref t) => {
|
||||||
|
|
|
@ -1866,7 +1866,7 @@ impl<'a> fmt::Display for Initializer<'a> {
|
||||||
let Initializer(s) = *self;
|
let Initializer(s) = *self;
|
||||||
if s.is_empty() { return Ok(()); }
|
if s.is_empty() { return Ok(()); }
|
||||||
write!(f, "<code> = </code>")?;
|
write!(f, "<code> = </code>")?;
|
||||||
write!(f, "<code>{}</code>", s)
|
write!(f, "<code>{}</code>", Escape(s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2106,7 +2106,7 @@ fn assoc_const(w: &mut fmt::Formatter,
|
||||||
|
|
||||||
write!(w, ": {}", ty)?;
|
write!(w, ": {}", ty)?;
|
||||||
if let Some(default) = default {
|
if let Some(default) = default {
|
||||||
write!(w, " = {}", default)?;
|
write!(w, " = {}", Escape(default))?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -4419,11 +4419,7 @@ impl<'a> Parser<'a> {
|
||||||
p.forbid_lifetime()?;
|
p.forbid_lifetime()?;
|
||||||
let lo = p.span.lo;
|
let lo = p.span.lo;
|
||||||
let ident = p.parse_ident()?;
|
let ident = p.parse_ident()?;
|
||||||
let found_eq = p.eat(&token::Eq);
|
p.expect(&token::Eq)?;
|
||||||
if !found_eq {
|
|
||||||
let span = p.span;
|
|
||||||
p.span_warn(span, "whoops, no =?");
|
|
||||||
}
|
|
||||||
let ty = p.parse_ty()?;
|
let ty = p.parse_ty()?;
|
||||||
let hi = ty.span.hi;
|
let hi = ty.span.hi;
|
||||||
let span = mk_sp(lo, hi);
|
let span = mk_sp(lo, hi);
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
|
|
||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
use std::{i8, i16, i32, i64, isize};
|
use std::{i8, i16, i32, i64, isize};
|
||||||
use std::{u8, u16, u32, u64, usize};
|
use std::{u8, u16, u32, u64, usize};
|
||||||
|
|
||||||
|
@ -26,10 +25,15 @@ const A_I8_T
|
||||||
//~| found `u8` [E0250]
|
//~| found `u8` [E0250]
|
||||||
= [0; (i8::MAX as usize) + 1];
|
= [0; (i8::MAX as usize) + 1];
|
||||||
|
|
||||||
fn main() {
|
|
||||||
foo(&A_I8_T[..]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn foo<T:fmt::Debug>(x: T) {
|
const A_CHAR_USIZE
|
||||||
println!("{:?}", x);
|
: [u32; 5u8 as char as usize]
|
||||||
}
|
= [0; 5];
|
||||||
|
|
||||||
|
|
||||||
|
const A_BAD_CHAR_USIZE
|
||||||
|
: [u32; 5i8 as char as usize]
|
||||||
|
//~^ ERROR only `u8` can be cast as `char`, not `i8`
|
||||||
|
= [0; 5];
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
static foo: i32 = 0;
|
||||||
|
//~^ NOTE static variable defined here
|
||||||
|
|
||||||
|
fn bar(foo: i32) {}
|
||||||
|
//~^ ERROR static variables cannot be referenced in a pattern, use a `const` instead
|
||||||
|
|
||||||
|
mod submod {
|
||||||
|
pub static answer: i32 = 42;
|
||||||
|
//~^ NOTE static variable defined here
|
||||||
|
}
|
||||||
|
|
||||||
|
use self::submod::answer;
|
||||||
|
//~^ NOTE static variable imported here
|
||||||
|
|
||||||
|
fn question(answer: i32) {}
|
||||||
|
//~^ ERROR static variables cannot be referenced in a pattern, use a `const` instead
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// compile-flags: -Z parse-only -Z continue-parse-after-error
|
||||||
|
|
||||||
|
pub fn test<W, I: Iterator<Item=(), W> >() {
|
||||||
|
//~^ ERROR expected `=`, found `>`
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// check for const_err regressions
|
||||||
|
|
||||||
|
#![deny(const_err)]
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _ = ((-1 as i8) << 8 - 1) as f32;
|
||||||
|
let _ = 0u8 as char;
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// Test that we HTML-escape Rust expressions, where HTML special chars
|
||||||
|
// can occur, and we know it's definitely not markup.
|
||||||
|
|
||||||
|
// @has escape_rust_expr/constant.CONST_S.html '//pre[@class="rust const"]' '"<script>"'
|
||||||
|
pub const CONST_S: &'static str = "<script>";
|
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// Ensure constant and array length values are not taken from source
|
||||||
|
// code, which wreaks havoc with macros.
|
||||||
|
|
||||||
|
#![feature(associated_consts)]
|
||||||
|
|
||||||
|
macro_rules! make {
|
||||||
|
($n:expr) => {
|
||||||
|
pub struct S;
|
||||||
|
|
||||||
|
// @has issue_33302/constant.CST.html \
|
||||||
|
// '//pre[@class="rust const"]' 'pub const CST: i32 = 4 * 4'
|
||||||
|
pub const CST: i32 = ($n * $n);
|
||||||
|
// @has issue_33302/static.ST.html \
|
||||||
|
// '//pre[@class="rust static"]' 'pub static ST: i32 = 4 * 4'
|
||||||
|
pub static ST: i32 = ($n * $n);
|
||||||
|
|
||||||
|
pub trait T<X> {
|
||||||
|
fn ignore(_: &X) {}
|
||||||
|
const C: X;
|
||||||
|
// @has issue_33302/trait.T.html \
|
||||||
|
// '//*[@class="rust trait"]' 'const D: i32 = 4 * 4;'
|
||||||
|
// @has - '//*[@id="associatedconstant.D"]' 'const D: i32 = 4 * 4'
|
||||||
|
const D: i32 = ($n * $n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @has issue_33302/struct.S.html \
|
||||||
|
// '//h3[@class="impl"]' 'impl T<[i32; 4 * 4]> for S'
|
||||||
|
// @has - '//*[@id="associatedconstant.C"]' 'const C: [i32; 4 * 4] = [0; 4 * 4]'
|
||||||
|
// @has - '//*[@id="associatedconstant.D"]' 'const D: i32 = 4 * 4'
|
||||||
|
impl T<[i32; ($n * $n)]> for S {
|
||||||
|
const C: [i32; ($n * $n)] = [0; ($n * $n)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
make!(4);
|
Loading…
Reference in New Issue