Skip to content

Commit 1e1f25e

Browse files
committed
Auto merge of #65196 - Centril:rollup-q06lcxm, r=Centril
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
2 parents d304f5c + bc7df81 commit 1e1f25e

24 files changed

+469
-309
lines changed

src/libcore/cell.rs

+46-46
Original file line numberDiff line numberDiff line change
@@ -229,52 +229,6 @@ pub struct Cell<T: ?Sized> {
229229
value: UnsafeCell<T>,
230230
}
231231

232-
impl<T:Copy> Cell<T> {
233-
/// Returns a copy of the contained value.
234-
///
235-
/// # Examples
236-
///
237-
/// ```
238-
/// use std::cell::Cell;
239-
///
240-
/// let c = Cell::new(5);
241-
///
242-
/// let five = c.get();
243-
/// ```
244-
#[inline]
245-
#[stable(feature = "rust1", since = "1.0.0")]
246-
pub fn get(&self) -> T {
247-
unsafe{ *self.value.get() }
248-
}
249-
250-
/// Updates the contained value using a function and returns the new value.
251-
///
252-
/// # Examples
253-
///
254-
/// ```
255-
/// #![feature(cell_update)]
256-
///
257-
/// use std::cell::Cell;
258-
///
259-
/// let c = Cell::new(5);
260-
/// let new = c.update(|x| x + 1);
261-
///
262-
/// assert_eq!(new, 6);
263-
/// assert_eq!(c.get(), 6);
264-
/// ```
265-
#[inline]
266-
#[unstable(feature = "cell_update", issue = "50186")]
267-
pub fn update<F>(&self, f: F) -> T
268-
where
269-
F: FnOnce(T) -> T,
270-
{
271-
let old = self.get();
272-
let new = f(old);
273-
self.set(new);
274-
new
275-
}
276-
}
277-
278232
#[stable(feature = "rust1", since = "1.0.0")]
279233
unsafe impl<T: ?Sized> Send for Cell<T> where T: Send {}
280234

@@ -448,6 +402,52 @@ impl<T> Cell<T> {
448402
}
449403
}
450404

405+
impl<T:Copy> Cell<T> {
406+
/// Returns a copy of the contained value.
407+
///
408+
/// # Examples
409+
///
410+
/// ```
411+
/// use std::cell::Cell;
412+
///
413+
/// let c = Cell::new(5);
414+
///
415+
/// let five = c.get();
416+
/// ```
417+
#[inline]
418+
#[stable(feature = "rust1", since = "1.0.0")]
419+
pub fn get(&self) -> T {
420+
unsafe{ *self.value.get() }
421+
}
422+
423+
/// Updates the contained value using a function and returns the new value.
424+
///
425+
/// # Examples
426+
///
427+
/// ```
428+
/// #![feature(cell_update)]
429+
///
430+
/// use std::cell::Cell;
431+
///
432+
/// let c = Cell::new(5);
433+
/// let new = c.update(|x| x + 1);
434+
///
435+
/// assert_eq!(new, 6);
436+
/// assert_eq!(c.get(), 6);
437+
/// ```
438+
#[inline]
439+
#[unstable(feature = "cell_update", issue = "50186")]
440+
pub fn update<F>(&self, f: F) -> T
441+
where
442+
F: FnOnce(T) -> T,
443+
{
444+
let old = self.get();
445+
let new = f(old);
446+
self.set(new);
447+
new
448+
}
449+
}
450+
451451
impl<T: ?Sized> Cell<T> {
452452
/// Returns a raw pointer to the underlying data in this cell.
453453
///

src/libcore/macros.rs

+32-15
Original file line numberDiff line numberDiff line change
@@ -520,57 +520,74 @@ macro_rules! unreachable {
520520
});
521521
}
522522

523-
/// Indicates unfinished code.
523+
/// Indicates unfinished code by panicking with a message of "not yet implemented".
524524
///
525-
/// This can be useful if you are prototyping and are just looking to have your
526-
/// code type-check, or if you're implementing a trait that requires multiple
527-
/// methods, and you're only planning on using one of them.
525+
/// This allows the your code to type-check, which is useful if you are prototyping or
526+
/// implementing a trait that requires multiple methods which you don't plan of using all of.
528527
///
529528
/// There is no difference between `unimplemented!` and `todo!` apart from the
530529
/// name.
531530
///
532531
/// # Panics
533532
///
534-
/// This will always [panic!](macro.panic.html)
533+
/// This will always [panic!](macro.panic.html) because `unimplemented!` is just a
534+
/// shorthand for `panic!` with a fixed, specific message.
535+
///
536+
/// Like `panic!`, this macro has a second form for displaying custom values.
535537
///
536538
/// # Examples
537539
///
538540
/// Here's an example of some in-progress code. We have a trait `Foo`:
539541
///
540542
/// ```
541543
/// trait Foo {
542-
/// fn bar(&self);
544+
/// fn bar(&self) -> u8;
543545
/// fn baz(&self);
546+
/// fn qux(&self) -> Result<u64, ()>;
544547
/// }
545548
/// ```
546549
///
547-
/// We want to implement `Foo` on one of our types, but we also want to work on
548-
/// just `bar()` first. In order for our code to compile, we need to implement
549-
/// `baz()`, so we can use `unimplemented!`:
550+
/// We want to implement `Foo` for 'MyStruct', but so far we only know how to
551+
/// implement the `bar()` function. `baz()` and `qux()` will still need to be defined
552+
/// in our implementation of `Foo`, but we can use `unimplemented!` in their definitions
553+
/// to allow our code to compile.
554+
///
555+
/// In the meantime, we want to have our program stop running once these
556+
/// unimplemented functions are reached.
550557
///
551558
/// ```
552559
/// # trait Foo {
553-
/// # fn bar(&self);
560+
/// # fn bar(&self) -> u8;
554561
/// # fn baz(&self);
562+
/// # fn qux(&self) -> Result<u64, ()>;
555563
/// # }
556564
/// struct MyStruct;
557565
///
558566
/// impl Foo for MyStruct {
559-
/// fn bar(&self) {
560-
/// // implementation goes here
567+
/// fn bar(&self) -> u8 {
568+
/// 1 + 1
561569
/// }
562570
///
563571
/// fn baz(&self) {
564-
/// // let's not worry about implementing baz() for now
572+
/// // We aren't sure how to even start writing baz yet,
573+
/// // so we have no logic here at all.
574+
/// // This will display "thread 'main' panicked at 'not yet implemented'".
565575
/// unimplemented!();
566576
/// }
577+
///
578+
/// fn qux(&self) -> Result<u64, ()> {
579+
/// let n = self.bar();
580+
/// // We have some logic here,
581+
/// // so we can use unimplemented! to display what we have so far.
582+
/// // This will display:
583+
/// // "thread 'main' panicked at 'not yet implemented: we need to divide by 2'".
584+
/// unimplemented!("we need to divide by {}", n);
585+
/// }
567586
/// }
568587
///
569588
/// fn main() {
570589
/// let s = MyStruct;
571590
/// s.bar();
572-
///
573-
/// // we aren't even using baz() yet, so this is fine.
574591
/// }
575592
/// ```
576593
#[macro_export]

src/librustc/infer/error_reporting/mod.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
935935
.filter(|(a, b)| a == b)
936936
.count();
937937
let len = sub1.len() - common_default_params;
938+
let consts_offset = len - sub1.consts().count();
938939

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

999+
// Do the same for const arguments, if they are equal, do not highlight and
1000+
// elide them from the output.
1001+
let const_arguments = sub1.consts().zip(sub2.consts());
1002+
for (i, (ca1, ca2)) in const_arguments.enumerate() {
1003+
let i = i + consts_offset;
1004+
if ca1 == ca2 {
1005+
values.0.push_normal("_");
1006+
values.1.push_normal("_");
1007+
} else {
1008+
values.0.push_highlighted(ca1.to_string());
1009+
values.1.push_highlighted(ca2.to_string());
1010+
}
1011+
self.push_comma(&mut values.0, &mut values.1, len, i);
1012+
}
1013+
9971014
// Close the type argument bracket.
9981015
// Only draw `<...>` if there're lifetime/type arguments.
9991016
if len > 0 {

src/librustc/ty/flags.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,9 @@ impl FlagComputation {
250250
ConstValue::Placeholder(_) => {
251251
self.add_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_CT_PLACEHOLDER);
252252
}
253-
_ => {},
253+
ConstValue::Scalar(_) => { }
254+
ConstValue::Slice { data: _, start: _, end: _ } => { }
255+
ConstValue::ByRef { alloc: _, offset: _ } => { }
254256
}
255257
}
256258

src/librustc/ty/fold.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -911,13 +911,15 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
911911
}
912912

913913
fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> bool {
914-
if let ty::Const {
915-
val: ConstValue::Infer(ty::InferConst::Canonical(debruijn, _)),
916-
..
917-
} = *ct {
918-
debruijn >= self.outer_index
919-
} else {
920-
false
914+
// we don't have a `visit_infer_const` callback, so we have to
915+
// hook in here to catch this case (annoying...), but
916+
// otherwise we do want to remember to visit the rest of the
917+
// const, as it has types/regions embedded in a lot of other
918+
// places.
919+
match ct.val {
920+
ConstValue::Infer(ty::InferConst::Canonical(debruijn, _))
921+
if debruijn >= self.outer_index => true,
922+
_ => ct.super_visit_with(self),
921923
}
922924
}
923925
}

src/librustc/ty/print/pretty.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ pub trait PrettyPrinter<'tcx>:
689689
if self.tcx().sess.verbose() {
690690
p!(write(
691691
" closure_kind_ty={:?} closure_sig_ty={:?}",
692-
substs.as_closure().kind(did, self.tcx()),
692+
substs.as_closure().kind_ty(did, self.tcx()),
693693
substs.as_closure().sig_ty(did, self.tcx())
694694
));
695695
}
@@ -698,7 +698,9 @@ pub trait PrettyPrinter<'tcx>:
698698
},
699699
ty::Array(ty, sz) => {
700700
p!(write("["), print(ty), write("; "));
701-
if let ConstValue::Unevaluated(..) = sz.val {
701+
if self.tcx().sess.verbose() {
702+
p!(write("{:?}", sz));
703+
} else if let ConstValue::Unevaluated(..) = sz.val {
702704
// do not try to evalute unevaluated constants. If we are const evaluating an
703705
// array length anon const, rustc will (with debug assertions) print the
704706
// constant's path. Which will end up here again.
@@ -855,6 +857,11 @@ pub trait PrettyPrinter<'tcx>:
855857
) -> Result<Self::Const, Self::Error> {
856858
define_scoped_cx!(self);
857859

860+
if self.tcx().sess.verbose() {
861+
p!(write("Const({:?}: {:?})", ct.val, ct.ty));
862+
return Ok(self);
863+
}
864+
858865
let u8 = self.tcx().types.u8;
859866
if let ty::FnDef(did, substs) = ct.ty.kind {
860867
p!(print_value_path(did, substs));

src/librustc/ty/sty.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2203,7 +2203,9 @@ impl<'tcx> TyS<'tcx> {
22032203
_ => bug!("cannot convert type `{:?}` to a closure kind", self),
22042204
},
22052205

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

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

src/librustc_passes/error_codes.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,34 @@ fn main() {
286286
```
287287
"##,
288288

289+
E0561: r##"
290+
A non-ident or non-wildcard pattern has been used as a parameter of a function
291+
pointer type.
292+
293+
Erroneous code example:
294+
295+
```compile_fail,E0561
296+
type A1 = fn(mut param: u8); // error!
297+
type A2 = fn(&param: u32); // error!
298+
```
299+
300+
When using an alias over a function type, you cannot e.g. denote a parameter as
301+
being mutable.
302+
303+
To fix the issue, remove patterns (`_` is allowed though). Example:
304+
305+
```
306+
type A1 = fn(param: u8); // ok!
307+
type A2 = fn(_: u32); // ok!
308+
```
309+
310+
You can also omit the parameter name:
311+
312+
```
313+
type A3 = fn(i16); // ok!
314+
```
315+
"##,
316+
289317
E0571: r##"
290318
A `break` statement with an argument appeared in a non-`loop` loop.
291319
@@ -503,7 +531,6 @@ Switch to the Rust 2018 edition to use `async fn`.
503531
;
504532
E0226, // only a single explicit lifetime bound is permitted
505533
E0472, // asm! is unsupported on this target
506-
E0561, // patterns aren't allowed in function pointer types
507534
E0567, // auto traits can not have generic parameters
508535
E0568, // auto traits can not have super traits
509536
E0666, // nested `impl Trait` is illegal

src/librustc_traits/evaluate_obligation.rs

+2
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ fn evaluate_obligation<'tcx>(
1717
tcx: TyCtxt<'tcx>,
1818
canonical_goal: CanonicalPredicateGoal<'tcx>,
1919
) -> Result<EvaluationResult, OverflowError> {
20+
debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal);
2021
tcx.infer_ctxt().enter_with_canonical(
2122
DUMMY_SP,
2223
&canonical_goal,
2324
|ref infcx, goal, _canonical_inference_vars| {
25+
debug!("evaluate_obligation: goal={:#?}", goal);
2426
let ParamEnvAnd {
2527
param_env,
2628
value: predicate,

src/librustc_typeck/check/demand.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
349349

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

354358
match (&expr.kind, &expected.kind, &checked_ty.kind) {
355359
(_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) {

src/librustc_typeck/check/expr.rs

+2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
8787
}
8888

8989
if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
90+
self.suggest_ref_or_into(&mut err, expr, expected_ty, ty);
91+
9092
let expr = match &expr.kind {
9193
ExprKind::DropTemps(expr) => expr,
9294
_ => expr,

0 commit comments

Comments
 (0)