Skip to content

Commit

Permalink
Auto merge of #65196 - Centril:rollup-q06lcxm, r=Centril
Browse files Browse the repository at this point in the history
Rollup of 8 pull requests

Successful merges:

 - #64726 (rewrite documentation for unimplemented! to clarify use)
 - #65040 (syntax: more cleanups in item and function signature parsing)
 - #65046 (Make `Cell::new` method come first in documentation)
 - #65098 (Add long error explanation for E0561)
 - #65150 (Suggest dereferencing boolean reference when used in 'if' or 'while')
 - #65154 (Fix const generic arguments not displaying in types mismatch diagnostic)
 - #65181 (fix bug in folding for constants)
 - #65187 (use 'invalid argument' for vxWorks)

Failed merges:

 - #65179 (Add long error explanation for E0567)

r? @ghost
  • Loading branch information
bors committed Oct 8, 2019
2 parents d304f5c + bc7df81 commit 1e1f25e
Show file tree
Hide file tree
Showing 24 changed files with 469 additions and 309 deletions.
92 changes: 46 additions & 46 deletions src/libcore/cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,52 +229,6 @@ pub struct Cell<T: ?Sized> {
value: UnsafeCell<T>,
}

impl<T:Copy> Cell<T> {
/// Returns a copy of the contained value.
///
/// # Examples
///
/// ```
/// use std::cell::Cell;
///
/// let c = Cell::new(5);
///
/// let five = c.get();
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get(&self) -> T {
unsafe{ *self.value.get() }
}

/// Updates the contained value using a function and returns the new value.
///
/// # Examples
///
/// ```
/// #![feature(cell_update)]
///
/// use std::cell::Cell;
///
/// let c = Cell::new(5);
/// let new = c.update(|x| x + 1);
///
/// assert_eq!(new, 6);
/// assert_eq!(c.get(), 6);
/// ```
#[inline]
#[unstable(feature = "cell_update", issue = "50186")]
pub fn update<F>(&self, f: F) -> T
where
F: FnOnce(T) -> T,
{
let old = self.get();
let new = f(old);
self.set(new);
new
}
}

#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<T: ?Sized> Send for Cell<T> where T: Send {}

Expand Down Expand Up @@ -448,6 +402,52 @@ impl<T> Cell<T> {
}
}

impl<T:Copy> Cell<T> {
/// Returns a copy of the contained value.
///
/// # Examples
///
/// ```
/// use std::cell::Cell;
///
/// let c = Cell::new(5);
///
/// let five = c.get();
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get(&self) -> T {
unsafe{ *self.value.get() }
}

/// Updates the contained value using a function and returns the new value.
///
/// # Examples
///
/// ```
/// #![feature(cell_update)]
///
/// use std::cell::Cell;
///
/// let c = Cell::new(5);
/// let new = c.update(|x| x + 1);
///
/// assert_eq!(new, 6);
/// assert_eq!(c.get(), 6);
/// ```
#[inline]
#[unstable(feature = "cell_update", issue = "50186")]
pub fn update<F>(&self, f: F) -> T
where
F: FnOnce(T) -> T,
{
let old = self.get();
let new = f(old);
self.set(new);
new
}
}

impl<T: ?Sized> Cell<T> {
/// Returns a raw pointer to the underlying data in this cell.
///
Expand Down
47 changes: 32 additions & 15 deletions src/libcore/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,57 +520,74 @@ macro_rules! unreachable {
});
}

/// Indicates unfinished code.
/// Indicates unfinished code by panicking with a message of "not yet implemented".
///
/// This can be useful if you are prototyping and are just looking to have your
/// code type-check, or if you're implementing a trait that requires multiple
/// methods, and you're only planning on using one of them.
/// This allows the your code to type-check, which is useful if you are prototyping or
/// implementing a trait that requires multiple methods which you don't plan of using all of.
///
/// There is no difference between `unimplemented!` and `todo!` apart from the
/// name.
///
/// # Panics
///
/// This will always [panic!](macro.panic.html)
/// This will always [panic!](macro.panic.html) because `unimplemented!` is just a
/// shorthand for `panic!` with a fixed, specific message.
///
/// Like `panic!`, this macro has a second form for displaying custom values.
///
/// # Examples
///
/// Here's an example of some in-progress code. We have a trait `Foo`:
///
/// ```
/// trait Foo {
/// fn bar(&self);
/// fn bar(&self) -> u8;
/// fn baz(&self);
/// fn qux(&self) -> Result<u64, ()>;
/// }
/// ```
///
/// We want to implement `Foo` on one of our types, but we also want to work on
/// just `bar()` first. In order for our code to compile, we need to implement
/// `baz()`, so we can use `unimplemented!`:
/// We want to implement `Foo` for 'MyStruct', but so far we only know how to
/// implement the `bar()` function. `baz()` and `qux()` will still need to be defined
/// in our implementation of `Foo`, but we can use `unimplemented!` in their definitions
/// to allow our code to compile.
///
/// In the meantime, we want to have our program stop running once these
/// unimplemented functions are reached.
///
/// ```
/// # trait Foo {
/// # fn bar(&self);
/// # fn bar(&self) -> u8;
/// # fn baz(&self);
/// # fn qux(&self) -> Result<u64, ()>;
/// # }
/// struct MyStruct;
///
/// impl Foo for MyStruct {
/// fn bar(&self) {
/// // implementation goes here
/// fn bar(&self) -> u8 {
/// 1 + 1
/// }
///
/// fn baz(&self) {
/// // let's not worry about implementing baz() for now
/// // We aren't sure how to even start writing baz yet,
/// // so we have no logic here at all.
/// // This will display "thread 'main' panicked at 'not yet implemented'".
/// unimplemented!();
/// }
///
/// fn qux(&self) -> Result<u64, ()> {
/// let n = self.bar();
/// // We have some logic here,
/// // so we can use unimplemented! to display what we have so far.
/// // This will display:
/// // "thread 'main' panicked at 'not yet implemented: we need to divide by 2'".
/// unimplemented!("we need to divide by {}", n);
/// }
/// }
///
/// fn main() {
/// let s = MyStruct;
/// s.bar();
///
/// // we aren't even using baz() yet, so this is fine.
/// }
/// ```
#[macro_export]
Expand Down
19 changes: 18 additions & 1 deletion src/librustc/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.filter(|(a, b)| a == b)
.count();
let len = sub1.len() - common_default_params;
let consts_offset = len - sub1.consts().count();

// Only draw `<...>` if there're lifetime/type arguments.
if len > 0 {
Expand Down Expand Up @@ -981,7 +982,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// ^ elided type as this type argument was the same in both sides
let type_arguments = sub1.types().zip(sub2.types());
let regions_len = sub1.regions().count();
for (i, (ta1, ta2)) in type_arguments.take(len).enumerate() {
let num_display_types = consts_offset - regions_len;
for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() {
let i = i + regions_len;
if ta1 == ta2 {
values.0.push_normal("_");
Expand All @@ -994,6 +996,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
self.push_comma(&mut values.0, &mut values.1, len, i);
}

// Do the same for const arguments, if they are equal, do not highlight and
// elide them from the output.
let const_arguments = sub1.consts().zip(sub2.consts());
for (i, (ca1, ca2)) in const_arguments.enumerate() {
let i = i + consts_offset;
if ca1 == ca2 {
values.0.push_normal("_");
values.1.push_normal("_");
} else {
values.0.push_highlighted(ca1.to_string());
values.1.push_highlighted(ca2.to_string());
}
self.push_comma(&mut values.0, &mut values.1, len, i);
}

// Close the type argument bracket.
// Only draw `<...>` if there're lifetime/type arguments.
if len > 0 {
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/ty/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,9 @@ impl FlagComputation {
ConstValue::Placeholder(_) => {
self.add_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_CT_PLACEHOLDER);
}
_ => {},
ConstValue::Scalar(_) => { }
ConstValue::Slice { data: _, start: _, end: _ } => { }
ConstValue::ByRef { alloc: _, offset: _ } => { }
}
}

Expand Down
16 changes: 9 additions & 7 deletions src/librustc/ty/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -911,13 +911,15 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
}

fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> bool {
if let ty::Const {
val: ConstValue::Infer(ty::InferConst::Canonical(debruijn, _)),
..
} = *ct {
debruijn >= self.outer_index
} else {
false
// we don't have a `visit_infer_const` callback, so we have to
// hook in here to catch this case (annoying...), but
// otherwise we do want to remember to visit the rest of the
// const, as it has types/regions embedded in a lot of other
// places.
match ct.val {
ConstValue::Infer(ty::InferConst::Canonical(debruijn, _))
if debruijn >= self.outer_index => true,
_ => ct.super_visit_with(self),
}
}
}
Expand Down
11 changes: 9 additions & 2 deletions src/librustc/ty/print/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,7 @@ pub trait PrettyPrinter<'tcx>:
if self.tcx().sess.verbose() {
p!(write(
" closure_kind_ty={:?} closure_sig_ty={:?}",
substs.as_closure().kind(did, self.tcx()),
substs.as_closure().kind_ty(did, self.tcx()),
substs.as_closure().sig_ty(did, self.tcx())
));
}
Expand All @@ -698,7 +698,9 @@ pub trait PrettyPrinter<'tcx>:
},
ty::Array(ty, sz) => {
p!(write("["), print(ty), write("; "));
if let ConstValue::Unevaluated(..) = sz.val {
if self.tcx().sess.verbose() {
p!(write("{:?}", sz));
} else if let ConstValue::Unevaluated(..) = sz.val {
// do not try to evalute unevaluated constants. If we are const evaluating an
// array length anon const, rustc will (with debug assertions) print the
// constant's path. Which will end up here again.
Expand Down Expand Up @@ -855,6 +857,11 @@ pub trait PrettyPrinter<'tcx>:
) -> Result<Self::Const, Self::Error> {
define_scoped_cx!(self);

if self.tcx().sess.verbose() {
p!(write("Const({:?}: {:?})", ct.val, ct.ty));
return Ok(self);
}

let u8 = self.tcx().types.u8;
if let ty::FnDef(did, substs) = ct.ty.kind {
p!(print_value_path(did, substs));
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2203,7 +2203,9 @@ impl<'tcx> TyS<'tcx> {
_ => bug!("cannot convert type `{:?}` to a closure kind", self),
},

Infer(_) => None,
// "Bound" types appear in canonical queries when the
// closure type is not yet known
Bound(..) | Infer(_) => None,

Error => Some(ty::ClosureKind::Fn),

Expand Down
29 changes: 28 additions & 1 deletion src/librustc_passes/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,34 @@ fn main() {
```
"##,

E0561: r##"
A non-ident or non-wildcard pattern has been used as a parameter of a function
pointer type.
Erroneous code example:
```compile_fail,E0561
type A1 = fn(mut param: u8); // error!
type A2 = fn(&param: u32); // error!
```
When using an alias over a function type, you cannot e.g. denote a parameter as
being mutable.
To fix the issue, remove patterns (`_` is allowed though). Example:
```
type A1 = fn(param: u8); // ok!
type A2 = fn(_: u32); // ok!
```
You can also omit the parameter name:
```
type A3 = fn(i16); // ok!
```
"##,

E0571: r##"
A `break` statement with an argument appeared in a non-`loop` loop.
Expand Down Expand Up @@ -503,7 +531,6 @@ Switch to the Rust 2018 edition to use `async fn`.
;
E0226, // only a single explicit lifetime bound is permitted
E0472, // asm! is unsupported on this target
E0561, // patterns aren't allowed in function pointer types
E0567, // auto traits can not have generic parameters
E0568, // auto traits can not have super traits
E0666, // nested `impl Trait` is illegal
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_traits/evaluate_obligation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ fn evaluate_obligation<'tcx>(
tcx: TyCtxt<'tcx>,
canonical_goal: CanonicalPredicateGoal<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal);
tcx.infer_ctxt().enter_with_canonical(
DUMMY_SP,
&canonical_goal,
|ref infcx, goal, _canonical_inference_vars| {
debug!("evaluate_obligation: goal={:#?}", goal);
let ParamEnvAnd {
param_env,
value: predicate,
Expand Down
6 changes: 5 additions & 1 deletion src/librustc_typeck/check/demand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

// If the span is from a macro, then it's hard to extract the text
// and make a good suggestion, so don't bother.
let is_macro = sp.from_expansion();
let is_desugaring = match sp.desugaring_kind() {
Some(k) => sp.is_desugaring(k),
None => false
};
let is_macro = sp.from_expansion() && !is_desugaring;

match (&expr.kind, &expected.kind, &checked_ty.kind) {
(_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) {
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_typeck/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}

if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
self.suggest_ref_or_into(&mut err, expr, expected_ty, ty);

let expr = match &expr.kind {
ExprKind::DropTemps(expr) => expr,
_ => expr,
Expand Down
Loading

0 comments on commit 1e1f25e

Please sign in to comment.