Skip to content

Rollup of 8 pull requests #65196

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Oct 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
3754691
Reorder methods of Cell
sinkuu Oct 3, 2019
0b0aeac
Suggest dereferencing boolean reference when used in 'if' or 'while'
XiangQingW Oct 6, 2019
5880ce3
Fix const arguments not displaying in types mismatch diagnostic.
skinnyBat Oct 6, 2019
8a164ac
Suggest dereferencing boolean reference when used in 'if' or 'while'
XiangQingW Oct 6, 2019
bbb69d1
Suggest dereferencing boolean reference when used in 'if' or 'while'
XiangQingW Oct 6, 2019
b7091e4
rewrite documentation for unimplemented!
andrewbanchich Sep 24, 2019
e0fe4be
syntax: cleanup associated const parsing.
Centril Oct 1, 2019
3bdbfbe
syntax: de-dups in item parsing.
Centril Oct 1, 2019
090f3fd
syntax: further item parsing cleanup
Centril Oct 1, 2019
7f9638d
syntax: unify trait parsing a bit.
Centril Oct 1, 2019
a7ba754
syntax: unify and simplify fn signature parsing.
Centril Oct 3, 2019
9c6582a
syntax: use `parse_extern_abi` more.
Centril Oct 7, 2019
6b23c22
syntax: refactor with new `fn parse_use_tree_glob_or_nested`.
Centril Oct 7, 2019
74eac92
Test diagnostic output of type mismatches for types that have const
skinnyBat Oct 7, 2019
4bf7eea
Add long error explanation for E0561
GuillaumeGomez Oct 4, 2019
8dd0008
Update ui tests
GuillaumeGomez Oct 4, 2019
25d04f8
make type-flags exhaustive
nikomatsakis Oct 7, 2019
0b58d9d
correct bug in the "has escaping regions" visitor
nikomatsakis Oct 7, 2019
bec0902
avoid ICE when extracting closure-kind-ty from a canonicalized value
nikomatsakis Oct 7, 2019
1dba4b0
fix ICE from debug output by using `kind_ty` in dumping closure
nikomatsakis Oct 7, 2019
08c0e84
add `debug!` to evaluate_obligation
nikomatsakis Oct 7, 2019
45f7186
use 'invalid argument' for vxWorks
BaoshanPang Oct 7, 2019
2f0618d
Rollup merge of #64726 - andrewbanchich:unimplemented, r=rkruppe
Centril Oct 8, 2019
4737095
Rollup merge of #65040 - Centril:items-cleanup, r=estebank
Centril Oct 8, 2019
a9777b3
Rollup merge of #65046 - sinkuu:cell_reorder, r=shepmaster
Centril Oct 8, 2019
73685ec
Rollup merge of #65098 - GuillaumeGomez:long-err-explanation-E0561, r…
Centril Oct 8, 2019
5422ed7
Rollup merge of #65150 - XiangQingW:master, r=estebank
Centril Oct 8, 2019
ecdb5e9
Rollup merge of #65154 - skinny121:const-arg-diagnostic, r=varkor
Centril Oct 8, 2019
f23c9f4
Rollup merge of #65181 - nikomatsakis:lazy-norm-anon-const-push-1, r=…
Centril Oct 8, 2019
bc7df81
Rollup merge of #65187 - Wind-River:master_before_merge, r=rkruppe
Centril Oct 8, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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