Skip to content

Commit

Permalink
Show file tree
Hide file tree
Showing 58 changed files with 709 additions and 72 deletions.
2 changes: 1 addition & 1 deletion src/doc/book/guessing-game.md
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ numbers. A bare number like above is actually shorthand for `^0.3.0`,
meaning "anything compatible with 0.3.0".
If we wanted to use only `0.3.0` exactly, we could say `rand="=0.3.0"`
(note the two equal signs).
And if we wanted to use the latest version we could use `*`.
And if we wanted to use the latest version we could use `rand="*"`.
We could also use a range of versions.
[Cargo’s documentation][cargodoc] contains more details.

Expand Down
2 changes: 2 additions & 0 deletions src/doc/book/the-stack-and-the-heap.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ The stack is very fast, and is where memory is allocated in Rust by default.
But the allocation is local to a function call, and is limited in size. The
heap, on the other hand, is slower, and is explicitly allocated by your
program. But it’s effectively unlimited in size, and is globally accessible.
Note this meaning of heap, which allocates arbitrary-sized blocks of memory in arbitrary
order, is quite different from the heap data structure.

# The Stack

Expand Down
3 changes: 2 additions & 1 deletion src/doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -3049,7 +3049,8 @@ as
== != < > <= >=
&&
||
= ..
.. ...
=
```

Operators at the same precedence level are evaluated left-to-right. [Unary
Expand Down
32 changes: 32 additions & 0 deletions src/libcollections/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,45 @@ pub trait RangeArgument<T> {
/// Start index (inclusive)
///
/// Return start value if present, else `None`.
///
/// # Examples
///
/// ```
/// #![feature(collections)]
/// #![feature(collections_range)]
///
/// extern crate collections;
///
/// # fn main() {
/// use collections::range::RangeArgument;
///
/// assert_eq!((..10).start(), None);
/// assert_eq!((3..10).start(), Some(&3));
/// # }
/// ```
fn start(&self) -> Option<&T> {
None
}

/// End index (exclusive)
///
/// Return end value if present, else `None`.
///
/// # Examples
///
/// ```
/// #![feature(collections)]
/// #![feature(collections_range)]
///
/// extern crate collections;
///
/// # fn main() {
/// use collections::range::RangeArgument;
///
/// assert_eq!((3..).end(), None);
/// assert_eq!((3..10).end(), Some(&10));
/// # }
/// ```
fn end(&self) -> Option<&T> {
None
}
Expand Down
19 changes: 19 additions & 0 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,25 @@ impl<T> Vec<T> {
/// Note that this will drop any excess capacity. Calling this and
/// converting back to a vector with `into_vec()` is equivalent to calling
/// `shrink_to_fit()`.
///
/// # Examples
///
/// ```
/// let v = vec![1, 2, 3];
///
/// let slice = v.into_boxed_slice();
/// ```
///
/// Any excess capacity is removed:
///
/// ```
/// let mut vec = Vec::with_capacity(10);
/// vec.extend([1, 2, 3].iter().cloned());
///
/// assert_eq!(vec.capacity(), 10);
/// let slice = vec.into_boxed_slice();
/// assert_eq!(slice.into_vec().capacity(), 3);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_boxed_slice(mut self) -> Box<[T]> {
unsafe {
Expand Down
6 changes: 6 additions & 0 deletions src/libcore/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ pub trait Unsize<T: ?Sized> {
/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's
/// managing some resource besides its own `size_of::<T>()` bytes.
///
/// ## What if I derive `Copy` on a type that can't?
///
/// If you try to derive `Copy` on a struct or enum, you will get a compile-time error.
/// Specifically, with structs you'll get [E0204](https://doc.rust-lang.org/error-index.html#E0204)
/// and with enums you'll get [E0205](https://doc.rust-lang.org/error-index.html#E0205).
///
/// ## When should my type be `Copy`?
///
/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing
Expand Down
34 changes: 33 additions & 1 deletion src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use hir::def::Def;
use hir::def_id::DefId;
use util::nodemap::{NodeMap, FnvHashSet};

use syntax_pos::{mk_sp, Span, ExpnId};
use syntax_pos::{BytePos, mk_sp, Span, ExpnId};
use syntax::codemap::{self, respan, Spanned};
use syntax::abi::Abi;
use syntax::ast::{Name, NodeId, DUMMY_NODE_ID, AsmDialect};
Expand Down Expand Up @@ -326,6 +326,38 @@ impl Generics {
pub fn is_parameterized(&self) -> bool {
self.is_lt_parameterized() || self.is_type_parameterized()
}

// Does return a span which includes lifetimes and type parameters,
// not where clause.
pub fn span(&self) -> Option<Span> {
if !self.is_parameterized() {
None
} else {
let mut span: Option<Span> = None;
for lifetime in self.lifetimes.iter() {
if let Some(ref mut span) = span {
let life_span = lifetime.lifetime.span;
span.hi = if span.hi > life_span.hi { span.hi } else { life_span.hi };
span.lo = if span.lo < life_span.lo { span.lo } else { life_span.lo };
} else {
span = Some(lifetime.lifetime.span.clone());
}
}
for ty_param in self.ty_params.iter() {
if let Some(ref mut span) = span {
span.lo = if span.lo < ty_param.span.lo { span.lo } else { ty_param.span.lo };
span.hi = if span.hi > ty_param.span.hi { span.hi } else { ty_param.span.hi };
} else {
span = Some(ty_param.span.clone());
}
}
if let Some(ref mut span) = span {
span.lo = span.lo - BytePos(1);
span.hi = span.hi + BytePos(1);
}
span
}
}
}

/// A `where` clause in a definition
Expand Down
13 changes: 9 additions & 4 deletions src/librustc/middle/astconv_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn prohibit_type_params(self, segments: &[ast::PathSegment]) {
for segment in segments {
for typ in segment.parameters.types() {
span_err!(self.sess, typ.span, E0109,
"type parameters are not allowed on this type");
struct_span_err!(self.sess, typ.span, E0109,
"type parameters are not allowed on this type")
.span_label(typ.span, &format!("type parameter not allowed"))
.emit();
break;
}
for lifetime in segment.parameters.lifetimes() {
span_err!(self.sess, lifetime.span, E0110,
"lifetime parameters are not allowed on this type");
struct_span_err!(self.sess, lifetime.span, E0110,
"lifetime parameters are not allowed on this type")
.span_label(lifetime.span,
&format!("lifetime parameter not allowed on this type"))
.emit();
break;
}
for binding in segment.parameters.bindings() {
Expand Down
7 changes: 5 additions & 2 deletions src/librustc/middle/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,11 @@ fn find_item(item: &Item, ctxt: &mut EntryContext, at_root: bool) {
if ctxt.attr_main_fn.is_none() {
ctxt.attr_main_fn = Some((item.id, item.span));
} else {
span_err!(ctxt.session, item.span, E0137,
"multiple functions with a #[main] attribute");
struct_span_err!(ctxt.session, item.span, E0137,
"multiple functions with a #[main] attribute")
.span_label(item.span, &format!("additional #[main] function"))
.span_label(ctxt.attr_main_fn.unwrap().1, &format!("first #[main] function"))
.emit();
}
},
EntryPointType::Start => {
Expand Down
1 change: 1 addition & 0 deletions src/librustc_const_eval/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ fn check_arms(cx: &MatchCheckCtxt,
hir::MatchSource::Normal => {
let mut err = struct_span_err!(cx.tcx.sess, pat.span, E0001,
"unreachable pattern");
err.span_label(pat.span, &format!("this is an unreachable pattern"));
// if we had a catchall pattern, hint at that
for row in &seen.0 {
if pat_is_catchall(&cx.tcx.def_map.borrow(), row[0].0) {
Expand Down
8 changes: 7 additions & 1 deletion src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,13 @@ fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>,
name)
}
ResolutionError::IsNotATrait(name) => {
struct_span_err!(resolver.session, span, E0404, "`{}` is not a trait", name)
let mut err = struct_span_err!(resolver.session,
span,
E0404,
"`{}` is not a trait",
name);
err.span_label(span, &format!("not a trait"));
err
}
ResolutionError::UndeclaredTraitName(name, candidates) => {
let mut err = struct_span_err!(resolver.session,
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1075,8 +1075,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
Ok((trait_ref, projection_bounds))
}
_ => {
span_err!(self.tcx().sess, ty.span, E0172,
"expected a reference to a trait");
struct_span_err!(self.tcx().sess, ty.span, E0172,
"expected a reference to a trait")
.span_label(ty.span, &format!("expected a trait"))
.emit();
Err(ErrorReported)
}
}
Expand All @@ -1086,6 +1088,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
"expected a path on the left-hand side \
of `+`, not `{}`",
pprust::ty_to_string(ty));
err.span_label(ty.span, &format!("expected a path"));
let hi = bounds.iter().map(|x| match *x {
hir::TraitTyParamBound(ref tr, _) => tr.span.hi,
hir::RegionTyParamBound(ref r) => r.span.hi,
Expand Down
6 changes: 4 additions & 2 deletions src/librustc_typeck/check/autoderef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@ impl<'a, 'gcx, 'tcx> Iterator for Autoderef<'a, 'gcx, 'tcx> {

if self.steps.len() == tcx.sess.recursion_limit.get() {
// We've reached the recursion limit, error gracefully.
span_err!(tcx.sess, self.span, E0055,
struct_span_err!(tcx.sess, self.span, E0055,
"reached the recursion limit while auto-dereferencing {:?}",
self.cur_ty);
self.cur_ty)
.span_label(self.span, &format!("deref recursion limit reached"))
.emit();
return None;
}

Expand Down
35 changes: 29 additions & 6 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2384,6 +2384,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
arg_count,
if arg_count == 1 {" was"} else {"s were"}),
error_code);

err.span_label(sp, &format!("expected {}{} parameter{}",
if variadic {"at least "} else {""},
expected_count,
if expected_count == 1 {""} else {"s"}));

let input_types = fn_inputs.iter().map(|i| format!("{:?}", i)).collect::<Vec<String>>();
if input_types.len() > 0 {
err.note(&format!("the following parameter type{} expected: {}",
Expand Down Expand Up @@ -3063,6 +3069,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
remaining_fields.insert(field.name, field);
}

let mut seen_fields = FnvHashMap();

let mut error_happened = false;

// Typecheck each field.
Expand All @@ -3071,13 +3079,25 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {

if let Some(v_field) = remaining_fields.remove(&field.name.node) {
expected_field_type = self.field_ty(field.span, v_field, substs);

seen_fields.insert(field.name.node, field.span);
} else {
error_happened = true;
expected_field_type = tcx.types.err;
if let Some(_) = variant.find_field_named(field.name.node) {
span_err!(self.tcx.sess, field.name.span, E0062,
"field `{}` specified more than once",
field.name.node);
let mut err = struct_span_err!(self.tcx.sess,
field.name.span,
E0062,
"field `{}` specified more than once",
field.name.node);

err.span_label(field.name.span, &format!("used more than once"));

if let Some(prev_span) = seen_fields.get(&field.name.node) {
err.span_label(*prev_span, &format!("first use of `{}`", field.name.node));
}

err.emit();
} else {
self.report_unknown_field(adt_ty, variant, field, ast_fields);
}
Expand Down Expand Up @@ -3147,9 +3167,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
};
if variant.is_none() || variant.unwrap().kind == ty::VariantKind::Tuple {
// Reject tuple structs for now, braced and unit structs are allowed.
span_err!(self.tcx.sess, span, E0071,
"`{}` does not name a struct or a struct variant",
pprust::path_to_string(path));
struct_span_err!(self.tcx.sess, path.span, E0071,
"`{}` does not name a struct or a struct variant",
pprust::path_to_string(path))
.span_label(path.span, &format!("not a struct"))
.emit();

return None;
}

Expand Down
14 changes: 9 additions & 5 deletions src/librustc_typeck/check/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// error types are considered "builtin"
if !lhs_ty.references_error() {
if let IsAssign::Yes = is_assign {
span_err!(self.tcx.sess, lhs_expr.span, E0368,
"binary assignment operation `{}=` \
cannot be applied to type `{}`",
op.node.as_str(),
lhs_ty);
struct_span_err!(self.tcx.sess, lhs_expr.span, E0368,
"binary assignment operation `{}=` \
cannot be applied to type `{}`",
op.node.as_str(),
lhs_ty)
.span_label(lhs_expr.span,
&format!("cannot use `{}=` on type `{}`",
op.node.as_str(), lhs_ty))
.emit();
} else {
let mut err = struct_span_err!(self.tcx.sess, lhs_expr.span, E0369,
"binary operation `{}` cannot be applied to type `{}`",
Expand Down
15 changes: 12 additions & 3 deletions src/librustc_typeck/coherence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,16 +249,25 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
if let Some(impl_node_id) = tcx.map.as_local_node_id(impl_did) {
match tcx.map.find(impl_node_id) {
Some(hir_map::NodeItem(item)) => {
span_err!(tcx.sess, item.span, E0120,
"the Drop trait may only be implemented on structures");
let span = match item.node {
ItemImpl(_, _, _, _, ref ty, _) => {
ty.span
},
_ => item.span
};
struct_span_err!(tcx.sess, span, E0120,
"the Drop trait may only be implemented on structures")
.span_label(span,
&format!("implementing Drop requires a struct"))
.emit();
}
_ => {
bug!("didn't find impl in ast map");
}
}
} else {
bug!("found external impl of Drop trait on \
:omething other than a struct");
something other than a struct");
}
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/librustc_typeck/coherence/overlap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,18 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
self.tcx.sess, self.tcx.span_of_impl(impl_def_id).unwrap(), E0119,
"conflicting implementations of trait `{}`{}:",
overlap.trait_desc,
overlap.self_desc.map_or(String::new(),
|ty| format!(" for type `{}`", ty)));
overlap.self_desc.clone().map_or(String::new(),
|ty| format!(" for type `{}`", ty)));

match self.tcx.span_of_impl(overlap.with_impl) {
Ok(span) => {
err.span_note(span, "conflicting implementation is here:");
err.span_label(span,
&format!("first implementation here"));
err.span_label(self.tcx.span_of_impl(impl_def_id).unwrap(),
&format!("conflicting implementation{}",
overlap.self_desc
.map_or(String::new(),
|ty| format!(" for `{}`", ty))));
}
Err(cname) => {
err.note(&format!("conflicting implementation in crate `{}`",
Expand Down
Loading

0 comments on commit b30eff7

Please sign in to comment.