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:
bors 2016-05-04 14:26:28 -07:00
commit 7a0ccc458f
17 changed files with 305 additions and 95 deletions

View File

@ -8,7 +8,7 @@ well talk about Cargo, Rusts build system and package manager.
The first step to using Rust is to install it. Generally speaking, youll need The first step to using Rust is to install it. Generally speaking, youll need
an Internet connection to run the commands in this section, as well be an Internet connection to run the commands in this section, as well be
downloading Rust from the internet. downloading Rust from the Internet.
Well be showing off a number of commands using a terminal, and those lines all Well 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 @@ Lets 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:

View File

@ -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:

View File

@ -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) }

View File

@ -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

View File

@ -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, _) |

View File

@ -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,

View File

@ -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);
}); });

View File

@ -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),
}), }),
} }
} }

View File

@ -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) => {

View File

@ -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(())
} }

View File

@ -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);

View File

@ -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() {}

View File

@ -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() {
}

View File

@ -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() { }

View File

@ -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;
}

View File

@ -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>";

View File

@ -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);