Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a084b7a

Browse files
committedMay 18, 2022
Auto merge of #97135 - Dylan-DPC:rollup-06u9pqn, r=Dylan-DPC
Rollup of 6 pull requests Successful merges: - #94639 (Suggest dereferencing non-lval mutable reference on assignment) - #95979 (update coherence docs, fix generator + opaque type ICE) - #96378 (Mention traits and types involved in unstable trait upcasting) - #96917 (Make HashMap fall back to RtlGenRandom if BCryptGenRandom fails) - #97101 (Add tracking issue for ExitCode::exit_process) - #97123 (Clean fix for #96223) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 77972d2 + a2c2720 commit a084b7a

29 files changed

+636
-215
lines changed
 

‎compiler/rustc_middle/src/traits/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ pub enum Reveal {
6161
/// let x: <() as Assoc>::Output = true;
6262
/// }
6363
/// ```
64+
///
65+
/// We also do not reveal the hidden type of opaque types during
66+
/// type-checking.
6467
UserFacing,
6568

6669
/// At codegen time, all monomorphic projections will succeed.

‎compiler/rustc_trait_selection/src/traits/coherence.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ fn orphan_check_trait_ref<'tcx>(
645645
.substs
646646
.types()
647647
.flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate))
648-
.find(|ty| ty_is_local_constructor(*ty, in_crate));
648+
.find(|&ty| ty_is_local_constructor(tcx, ty, in_crate));
649649

650650
debug!("orphan_check_trait_ref: uncovered ty local_type: `{:?}`", local_type);
651651

@@ -677,7 +677,7 @@ fn contained_non_local_types<'tcx>(
677677
ty: Ty<'tcx>,
678678
in_crate: InCrate,
679679
) -> Vec<Ty<'tcx>> {
680-
if ty_is_local_constructor(ty, in_crate) {
680+
if ty_is_local_constructor(tcx, ty, in_crate) {
681681
Vec::new()
682682
} else {
683683
match fundamental_ty_inner_tys(tcx, ty) {
@@ -730,7 +730,7 @@ fn def_id_is_local(def_id: DefId, in_crate: InCrate) -> bool {
730730
}
731731
}
732732

733-
fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
733+
fn ty_is_local_constructor(tcx: TyCtxt<'_>, ty: Ty<'_>, in_crate: InCrate) -> bool {
734734
debug!("ty_is_local_constructor({:?})", ty);
735735

736736
match *ty.kind() {
@@ -789,11 +789,6 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
789789
false
790790
}
791791

792-
ty::Closure(..) => {
793-
// Similar to the `Opaque` case (#83613).
794-
false
795-
}
796-
797792
ty::Dynamic(ref tt, ..) => {
798793
if let Some(principal) = tt.principal() {
799794
def_id_is_local(principal.def_id(), in_crate)
@@ -804,8 +799,20 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
804799

805800
ty::Error(_) => true,
806801

807-
ty::Generator(..) | ty::GeneratorWitness(..) => {
808-
bug!("ty_is_local invoked on unexpected type: {:?}", ty)
802+
// These variants should never appear during coherence checking because they
803+
// cannot be named directly.
804+
//
805+
// They could be indirectly used through an opaque type. While using opaque types
806+
// in impls causes an error, this path can still be hit afterwards.
807+
//
808+
// See `test/ui/coherence/coherence-with-closure.rs` for an example where this
809+
// could happens.
810+
ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => {
811+
tcx.sess.delay_span_bug(
812+
DUMMY_SP,
813+
format!("ty_is_local invoked on closure or generator: {:?}", ty),
814+
);
815+
true
809816
}
810817
}
811818
}

‎compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,8 +1384,7 @@ trait InferCtxtPrivExt<'hir, 'tcx> {
13841384
fn mk_trait_obligation_with_new_self_ty(
13851385
&self,
13861386
param_env: ty::ParamEnv<'tcx>,
1387-
trait_ref: ty::PolyTraitPredicate<'tcx>,
1388-
new_self_ty: Ty<'tcx>,
1387+
trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
13891388
) -> PredicateObligation<'tcx>;
13901389

13911390
fn maybe_report_ambiguity(
@@ -1923,14 +1922,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
19231922
fn mk_trait_obligation_with_new_self_ty(
19241923
&self,
19251924
param_env: ty::ParamEnv<'tcx>,
1926-
trait_ref: ty::PolyTraitPredicate<'tcx>,
1927-
new_self_ty: Ty<'tcx>,
1925+
trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>,
19281926
) -> PredicateObligation<'tcx> {
1929-
assert!(!new_self_ty.has_escaping_bound_vars());
1930-
1931-
let trait_pred = trait_ref.map_bound_ref(|tr| ty::TraitPredicate {
1927+
let trait_pred = trait_ref_and_ty.map_bound_ref(|(tr, new_self_ty)| ty::TraitPredicate {
19321928
trait_ref: ty::TraitRef {
1933-
substs: self.tcx.mk_substs_trait(new_self_ty, &tr.trait_ref.substs[1..]),
1929+
substs: self.tcx.mk_substs_trait(*new_self_ty, &tr.trait_ref.substs[1..]),
19341930
..tr.trait_ref
19351931
},
19361932
..*tr

‎compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

Lines changed: 126 additions & 120 deletions
Large diffs are not rendered by default.

‎compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,22 +103,31 @@ pub struct SelectionContext<'cx, 'tcx> {
103103
/// require themselves.
104104
freshener: TypeFreshener<'cx, 'tcx>,
105105

106-
/// If `true`, indicates that the evaluation should be conservative
107-
/// and consider the possibility of types outside this crate.
106+
/// During coherence we have to assume that other crates may add
107+
/// additional impls which we currently don't know about.
108+
///
109+
/// To deal with this evaluation should be conservative
110+
/// and consider the possibility of impls from outside this crate.
108111
/// This comes up primarily when resolving ambiguity. Imagine
109112
/// there is some trait reference `$0: Bar` where `$0` is an
110113
/// inference variable. If `intercrate` is true, then we can never
111114
/// say for sure that this reference is not implemented, even if
112115
/// there are *no impls at all for `Bar`*, because `$0` could be
113116
/// bound to some type that in a downstream crate that implements
114-
/// `Bar`. This is the suitable mode for coherence. Elsewhere,
115-
/// though, we set this to false, because we are only interested
116-
/// in types that the user could actually have written --- in
117-
/// other words, we consider `$0: Bar` to be unimplemented if
117+
/// `Bar`.
118+
///
119+
/// Outside of coherence we set this to false because we are only
120+
/// interested in types that the user could actually have written.
121+
/// In other words, we consider `$0: Bar` to be unimplemented if
118122
/// there is no type that the user could *actually name* that
119123
/// would satisfy it. This avoids crippling inference, basically.
120124
intercrate: bool,
121-
125+
/// If `intercrate` is set, we remember predicates which were
126+
/// considered ambiguous because of impls potentially added in other crates.
127+
/// This is used in coherence to give improved diagnostics.
128+
/// We don't do his until we detect a coherence error because it can
129+
/// lead to false overflow results (#47139) and because always
130+
/// computing it may negatively impact performance.
122131
intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
123132

124133
/// The mode that trait queries run in, which informs our error handling
@@ -240,11 +249,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
240249
}
241250
}
242251

243-
/// Enables tracking of intercrate ambiguity causes. These are
244-
/// used in coherence to give improved diagnostics. We don't do
245-
/// this until we detect a coherence error because it can lead to
246-
/// false overflow results (#47139) and because it costs
247-
/// computation time.
252+
/// Enables tracking of intercrate ambiguity causes. See
253+
/// the documentation of [`Self::intercrate_ambiguity_causes`] for more.
248254
pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
249255
assert!(self.intercrate);
250256
assert!(self.intercrate_ambiguity_causes.is_none());

‎compiler/rustc_typeck/src/check/coercion.rs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ use rustc_session::parse::feature_err;
5858
use rustc_span::symbol::sym;
5959
use rustc_span::{self, BytePos, DesugaringKind, Span};
6060
use rustc_target::spec::abi::Abi;
61-
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
61+
use rustc_trait_selection::infer::InferCtxtExt as _;
62+
use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
6263
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode};
6364

6465
use smallvec::{smallvec, SmallVec};
@@ -615,7 +616,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
615616
)];
616617

617618
let mut has_unsized_tuple_coercion = false;
618-
let mut has_trait_upcasting_coercion = false;
619+
let mut has_trait_upcasting_coercion = None;
619620

620621
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
621622
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
@@ -635,7 +636,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
635636
&& data_a.principal_def_id() != data_b.principal_def_id()
636637
{
637638
debug!("coerce_unsized: found trait upcasting coercion");
638-
has_trait_upcasting_coercion = true;
639+
has_trait_upcasting_coercion = Some((self_ty, unsize_ty));
639640
}
640641
if let ty::Tuple(..) = unsize_ty.kind() {
641642
debug!("coerce_unsized: found unsized tuple coercion");
@@ -706,14 +707,19 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
706707
.emit();
707708
}
708709

709-
if has_trait_upcasting_coercion && !self.tcx().features().trait_upcasting {
710-
feature_err(
710+
if let Some((sub, sup)) = has_trait_upcasting_coercion
711+
&& !self.tcx().features().trait_upcasting
712+
{
713+
// Renders better when we erase regions, since they're not really the point here.
714+
let (sub, sup) = self.tcx.erase_regions((sub, sup));
715+
let mut err = feature_err(
711716
&self.tcx.sess.parse_sess,
712717
sym::trait_upcasting,
713718
self.cause.span,
714-
"trait upcasting coercion is experimental",
715-
)
716-
.emit();
719+
&format!("cannot cast `{sub}` to `{sup}`, trait upcasting coercion is experimental"),
720+
);
721+
err.note(&format!("required when coercing `{source}` into `{target}`"));
722+
err.emit();
717723
}
718724

719725
Ok(coercion)
@@ -962,6 +968,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
962968
.find_map(|(ty, steps)| self.probe(|_| coerce.unify(ty, target)).ok().map(|_| steps))
963969
}
964970

971+
/// Given a type, this function will calculate and return the type given
972+
/// for `<Ty as Deref>::Target` only if `Ty` also implements `DerefMut`.
973+
///
974+
/// This function is for diagnostics only, since it does not register
975+
/// trait or region sub-obligations. (presumably we could, but it's not
976+
/// particularly important for diagnostics...)
977+
pub fn deref_once_mutably_for_diagnostic(&self, expr_ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
978+
self.autoderef(rustc_span::DUMMY_SP, expr_ty).nth(1).and_then(|(deref_ty, _)| {
979+
self.infcx
980+
.type_implements_trait(
981+
self.infcx.tcx.lang_items().deref_mut_trait()?,
982+
expr_ty,
983+
ty::List::empty(),
984+
self.param_env,
985+
)
986+
.may_apply()
987+
.then(|| deref_ty)
988+
})
989+
}
990+
965991
/// Given some expressions, their known unified type and another expression,
966992
/// tries to unify the types, potentially inserting coercions on any of the
967993
/// provided expressions and returns their LUB (aka "common supertype").

‎compiler/rustc_typeck/src/check/demand.rs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -696,28 +696,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
696696
};
697697

698698
if let Some(hir::Node::Expr(hir::Expr {
699-
kind: hir::ExprKind::Assign(left_expr, ..),
699+
kind: hir::ExprKind::Assign(..),
700700
..
701701
})) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id))
702702
{
703703
if mutability == hir::Mutability::Mut {
704-
// Found the following case:
705-
// fn foo(opt: &mut Option<String>){ opt = None }
706-
// --- ^^^^
707-
// | |
708-
// consider dereferencing here: `*opt` |
709-
// expected mutable reference, found enum `Option`
710-
if sm.span_to_snippet(left_expr.span).is_ok() {
711-
return Some((
712-
left_expr.span.shrink_to_lo(),
713-
"consider dereferencing here to assign to the mutable \
714-
borrowed piece of memory"
715-
.to_string(),
716-
"*".to_string(),
717-
Applicability::MachineApplicable,
718-
true,
719-
));
720-
}
704+
// Suppressing this diagnostic, we'll properly print it in `check_expr_assign`
705+
return None;
721706
}
722707
}
723708

‎compiler/rustc_typeck/src/check/expr.rs

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ use rustc_span::lev_distance::find_best_match_for_name;
5151
use rustc_span::source_map::Span;
5252
use rustc_span::symbol::{kw, sym, Ident, Symbol};
5353
use rustc_span::{BytePos, Pos};
54+
use rustc_trait_selection::infer::InferCtxtExt;
5455
use rustc_trait_selection::traits::{self, ObligationCauseCode};
5556

5657
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -836,6 +837,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
836837
lhs: &'tcx hir::Expr<'tcx>,
837838
err_code: &'static str,
838839
op_span: Span,
840+
adjust_err: impl FnOnce(&mut DiagnosticBuilder<'tcx, ErrorGuaranteed>),
839841
) {
840842
if lhs.is_syntactic_place_expr() {
841843
return;
@@ -858,6 +860,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
858860
);
859861
});
860862

863+
adjust_err(&mut err);
864+
861865
err.emit();
862866
}
863867

@@ -1050,10 +1054,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10501054
return self.tcx.ty_error();
10511055
}
10521056

1053-
self.check_lhs_assignable(lhs, "E0070", span);
1054-
10551057
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
1056-
let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty, Some(lhs));
1058+
1059+
let suggest_deref_binop = |err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>,
1060+
rhs_ty: Ty<'tcx>| {
1061+
if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) {
1062+
// Can only assign if the type is sized, so if `DerefMut` yields a type that is
1063+
// unsized, do not suggest dereferencing it.
1064+
let lhs_deref_ty_is_sized = self
1065+
.infcx
1066+
.type_implements_trait(
1067+
self.tcx.lang_items().sized_trait().unwrap(),
1068+
lhs_deref_ty,
1069+
ty::List::empty(),
1070+
self.param_env,
1071+
)
1072+
.may_apply();
1073+
if lhs_deref_ty_is_sized && self.can_coerce(rhs_ty, lhs_deref_ty) {
1074+
err.span_suggestion_verbose(
1075+
lhs.span.shrink_to_lo(),
1076+
"consider dereferencing here to assign to the mutably borrowed value",
1077+
"*".to_string(),
1078+
Applicability::MachineApplicable,
1079+
);
1080+
}
1081+
}
1082+
};
1083+
1084+
self.check_lhs_assignable(lhs, "E0070", span, |err| {
1085+
let rhs_ty = self.check_expr(&rhs);
1086+
suggest_deref_binop(err, rhs_ty);
1087+
});
1088+
1089+
// This is (basically) inlined `check_expr_coercable_to_type`, but we want
1090+
// to suggest an additional fixup here in `suggest_deref_binop`.
1091+
let rhs_ty = self.check_expr_with_hint(&rhs, lhs_ty);
1092+
if let (_, Some(mut diag)) =
1093+
self.demand_coerce_diag(rhs, rhs_ty, lhs_ty, Some(lhs), AllowTwoPhase::No)
1094+
{
1095+
suggest_deref_binop(&mut diag, rhs_ty);
1096+
diag.emit();
1097+
}
10571098

10581099
self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
10591100

‎compiler/rustc_typeck/src/check/op.rs

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4141
return_ty
4242
};
4343

44-
self.check_lhs_assignable(lhs, "E0067", op.span);
44+
self.check_lhs_assignable(lhs, "E0067", op.span, |err| {
45+
if let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) {
46+
if self
47+
.lookup_op_method(
48+
lhs_deref_ty,
49+
Some(rhs_ty),
50+
Some(rhs),
51+
Op::Binary(op, IsAssign::Yes),
52+
)
53+
.is_ok()
54+
{
55+
// Suppress this error, since we already emitted
56+
// a deref suggestion in check_overloaded_binop
57+
err.delay_as_bug();
58+
}
59+
}
60+
});
4561

4662
ty
4763
}
@@ -404,16 +420,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
404420
(err, missing_trait, use_output)
405421
}
406422
};
407-
if let Ref(_, rty, _) = lhs_ty.kind() {
408-
if self.infcx.type_is_copy_modulo_regions(self.param_env, *rty, lhs_expr.span)
409-
&& self
410-
.lookup_op_method(
411-
*rty,
412-
Some(rhs_ty),
413-
Some(rhs_expr),
414-
Op::Binary(op, is_assign),
415-
)
416-
.is_ok()
423+
424+
let mut suggest_deref_binop = |lhs_deref_ty: Ty<'tcx>| {
425+
if self
426+
.lookup_op_method(
427+
lhs_deref_ty,
428+
Some(rhs_ty),
429+
Some(rhs_expr),
430+
Op::Binary(op, is_assign),
431+
)
432+
.is_ok()
417433
{
418434
if let Ok(lstring) = source_map.span_to_snippet(lhs_expr.span) {
419435
let msg = &format!(
@@ -423,7 +439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
423439
IsAssign::Yes => "=",
424440
IsAssign::No => "",
425441
},
426-
rty.peel_refs(),
442+
lhs_deref_ty.peel_refs(),
427443
lstring,
428444
);
429445
err.span_suggestion_verbose(
@@ -434,6 +450,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
434450
);
435451
}
436452
}
453+
};
454+
455+
// We should suggest `a + b` => `*a + b` if `a` is copy, and suggest
456+
// `a += b` => `*a += b` if a is a mut ref.
457+
if is_assign == IsAssign::Yes
458+
&& let Some(lhs_deref_ty) = self.deref_once_mutably_for_diagnostic(lhs_ty) {
459+
suggest_deref_binop(lhs_deref_ty);
460+
} else if is_assign == IsAssign::No
461+
&& let Ref(_, lhs_deref_ty, _) = lhs_ty.kind() {
462+
if self.infcx.type_is_copy_modulo_regions(self.param_env, *lhs_deref_ty, lhs_expr.span) {
463+
suggest_deref_binop(*lhs_deref_ty);
464+
}
437465
}
438466
if let Some(missing_trait) = missing_trait {
439467
let mut visitor = TypeParamVisitor(vec![]);

‎library/std/src/process.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1764,7 +1764,7 @@ impl ExitCode {
17641764
/// code.exit_process()
17651765
/// }
17661766
/// ```
1767-
#[unstable(feature = "exitcode_exit_method", issue = "none")]
1767+
#[unstable(feature = "exitcode_exit_method", issue = "97100")]
17681768
pub fn exit_process(self) -> ! {
17691769
exit(self.to_i32())
17701770
}

‎library/std/src/sys/windows/c.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,10 @@ if #[cfg(not(target_vendor = "uwp"))] {
788788

789789
#[link(name = "advapi32")]
790790
extern "system" {
791+
// Forbidden when targeting UWP
792+
#[link_name = "SystemFunction036"]
793+
pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
794+
791795
// Allowed but unused by UWP
792796
pub fn OpenProcessToken(
793797
ProcessHandle: HANDLE,

‎library/std/src/sys/windows/rand.rs

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,60 @@
11
use crate::io;
2+
use crate::lazy;
23
use crate::mem;
34
use crate::sys::c;
45

6+
/// The kinds of HashMap RNG that may be available
7+
#[derive(Clone, Copy, Debug, PartialEq)]
8+
enum HashMapRng {
9+
Preferred,
10+
Fallback,
11+
}
12+
513
pub fn hashmap_random_keys() -> (u64, u64) {
14+
match get_hashmap_rng() {
15+
HashMapRng::Preferred => {
16+
preferred_rng().expect("couldn't generate random bytes with preferred RNG")
17+
}
18+
HashMapRng::Fallback => {
19+
fallback_rng().expect("couldn't generate random bytes with fallback RNG")
20+
}
21+
}
22+
}
23+
24+
/// Returns the HashMap RNG that should be used
25+
///
26+
/// Panics if they are both broken
27+
fn get_hashmap_rng() -> HashMapRng {
28+
// Assume that if the preferred RNG is broken the first time we use it, it likely means
29+
// that: the DLL has failed to load, there is no point to calling it over-and-over again,
30+
// and we should cache the result
31+
static VALUE: lazy::SyncOnceCell<HashMapRng> = lazy::SyncOnceCell::new();
32+
*VALUE.get_or_init(choose_hashmap_rng)
33+
}
34+
35+
/// Test whether we should use the preferred or fallback RNG
36+
///
37+
/// If the preferred RNG is successful, we choose it. Otherwise, if the fallback RNG is successful,
38+
/// we choose that
39+
///
40+
/// Panics if both the preferred and the fallback RNG are both non-functional
41+
fn choose_hashmap_rng() -> HashMapRng {
42+
let preferred_error = match preferred_rng() {
43+
Ok(_) => return HashMapRng::Preferred,
44+
Err(e) => e,
45+
};
46+
47+
match fallback_rng() {
48+
Ok(_) => return HashMapRng::Fallback,
49+
Err(fallback_error) => panic!(
50+
"preferred RNG broken: `{}`, fallback RNG broken: `{}`",
51+
preferred_error, fallback_error
52+
),
53+
}
54+
}
55+
56+
/// Generate random numbers using the preferred RNG function (BCryptGenRandom)
57+
fn preferred_rng() -> Result<(u64, u64), io::Error> {
658
use crate::ptr;
759

860
let mut v = (0, 0);
@@ -14,8 +66,22 @@ pub fn hashmap_random_keys() -> (u64, u64) {
1466
c::BCRYPT_USE_SYSTEM_PREFERRED_RNG,
1567
)
1668
};
17-
if ret != 0 {
18-
panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
19-
}
20-
return v;
69+
70+
if ret == 0 { Ok(v) } else { Err(io::Error::last_os_error()) }
71+
}
72+
73+
/// Generate random numbers using the fallback RNG function (RtlGenRandom)
74+
#[cfg(not(target_vendor = "uwp"))]
75+
fn fallback_rng() -> Result<(u64, u64), io::Error> {
76+
let mut v = (0, 0);
77+
let ret =
78+
unsafe { c::RtlGenRandom(&mut v as *mut _ as *mut u8, mem::size_of_val(&v) as c::ULONG) };
79+
80+
if ret != 0 { Ok(v) } else { Err(io::Error::last_os_error()) }
81+
}
82+
83+
/// We can't use RtlGenRandom with UWP, so there is no fallback
84+
#[cfg(target_vendor = "uwp")]
85+
fn fallback_rng() -> Result<(u64, u64), io::Error> {
86+
Err(io::const_io_error!(io::ErrorKind::Unsupported, "RtlGenRandom() not supported on UWP"))
2187
}

‎src/test/ui/binop/issue-77910-1.stderr

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,14 @@ LL | assert_eq!(foo, y);
1212
error[E0277]: `for<'r> fn(&'r i32) -> &'r i32 {foo}` doesn't implement `Debug`
1313
--> $DIR/issue-77910-1.rs:8:5
1414
|
15+
LL | fn foo(s: &i32) -> &i32 {
16+
| --- consider calling this function
17+
...
1518
LL | assert_eq!(foo, y);
1619
| ^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
1720
|
1821
= help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}`
19-
= help: the following other types implement trait `Debug`:
20-
extern "C" fn() -> Ret
21-
extern "C" fn(A) -> Ret
22-
extern "C" fn(A, ...) -> Ret
23-
extern "C" fn(A, B) -> Ret
24-
extern "C" fn(A, B, ...) -> Ret
25-
extern "C" fn(A, B, C) -> Ret
26-
extern "C" fn(A, B, C, ...) -> Ret
27-
extern "C" fn(A, B, C, D) -> Ret
28-
and 68 others
22+
= help: use parentheses to call the function: `foo(s)`
2923
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
3024

3125
error: aborting due to 2 previous errors
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Test that encountering closures during coherence does not cause issues.
2+
#![feature(type_alias_impl_trait)]
3+
type OpaqueClosure = impl Sized;
4+
fn defining_use() -> OpaqueClosure {
5+
|| ()
6+
}
7+
8+
struct Wrapper<T>(T);
9+
trait Trait {}
10+
impl Trait for Wrapper<OpaqueClosure> {}
11+
//~^ ERROR cannot implement trait on type alias impl trait
12+
impl<T: Sync> Trait for Wrapper<T> {}
13+
//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
14+
15+
fn main() {}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error: cannot implement trait on type alias impl trait
2+
--> $DIR/coherence-with-closure.rs:10:24
3+
|
4+
LL | impl Trait for Wrapper<OpaqueClosure> {}
5+
| ^^^^^^^^^^^^^
6+
|
7+
note: type alias impl trait defined here
8+
--> $DIR/coherence-with-closure.rs:3:22
9+
|
10+
LL | type OpaqueClosure = impl Sized;
11+
| ^^^^^^^^^^
12+
13+
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
14+
--> $DIR/coherence-with-closure.rs:12:1
15+
|
16+
LL | impl Trait for Wrapper<OpaqueClosure> {}
17+
| ------------------------------------- first implementation here
18+
LL |
19+
LL | impl<T: Sync> Trait for Wrapper<T> {}
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueClosure>`
21+
22+
error: aborting due to 2 previous errors
23+
24+
For more information about this error, try `rustc --explain E0119`.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Test that encountering closures during coherence does not cause issues.
2+
#![feature(type_alias_impl_trait, generators)]
3+
type OpaqueGenerator = impl Sized;
4+
fn defining_use() -> OpaqueGenerator {
5+
|| {
6+
for i in 0..10 {
7+
yield i;
8+
}
9+
}
10+
}
11+
12+
struct Wrapper<T>(T);
13+
trait Trait {}
14+
impl Trait for Wrapper<OpaqueGenerator> {}
15+
//~^ ERROR cannot implement trait on type alias impl trait
16+
impl<T: Sync> Trait for Wrapper<T> {}
17+
//~^ ERROR conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
18+
19+
fn main() {}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error: cannot implement trait on type alias impl trait
2+
--> $DIR/coherence-with-generator.rs:14:24
3+
|
4+
LL | impl Trait for Wrapper<OpaqueGenerator> {}
5+
| ^^^^^^^^^^^^^^^
6+
|
7+
note: type alias impl trait defined here
8+
--> $DIR/coherence-with-generator.rs:3:24
9+
|
10+
LL | type OpaqueGenerator = impl Sized;
11+
| ^^^^^^^^^^
12+
13+
error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueGenerator>`
14+
--> $DIR/coherence-with-generator.rs:16:1
15+
|
16+
LL | impl Trait for Wrapper<OpaqueGenerator> {}
17+
| --------------------------------------- first implementation here
18+
LL |
19+
LL | impl<T: Sync> Trait for Wrapper<T> {}
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Wrapper<OpaqueGenerator>`
21+
22+
error: aborting due to 2 previous errors
23+
24+
For more information about this error, try `rustc --explain E0119`.

‎src/test/ui/feature-gates/feature-gate-trait_upcasting.stderr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
error[E0658]: trait upcasting coercion is experimental
1+
error[E0658]: cannot cast `dyn Bar` to `dyn Foo`, trait upcasting coercion is experimental
22
--> $DIR/feature-gate-trait_upcasting.rs:11:25
33
|
44
LL | let foo: &dyn Foo = bar;
55
| ^^^
66
|
77
= note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
88
= help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
9+
= note: required when coercing `&dyn Bar` into `&dyn Foo`
910

1011
error: aborting due to previous error
1112

‎src/test/ui/issues/issue-11515.stderr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
error[E0658]: trait upcasting coercion is experimental
1+
error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
22
--> $DIR/issue-11515.rs:9:33
33
|
44
LL | let test = box Test { func: closure };
55
| ^^^^^^^
66
|
77
= note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
88
= help: add `#![feature(trait_upcasting)]` to the crate attributes to enable
9+
= note: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>`
910

1011
error: aborting due to previous error
1112

‎src/test/ui/issues/issue-5239-1.stderr

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@ LL | let x = |ref x: isize| { x += 1; };
55
| -^^^^^
66
| |
77
| cannot use `+=` on type `&isize`
8-
|
9-
help: `+=` can be used on `isize`, you can dereference `x`
10-
|
11-
LL | let x = |ref x: isize| { *x += 1; };
12-
| +
138

149
error: aborting due to previous error
1510

‎src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ LL | foo::<S>(s);
55
| ^^^^^^^^ the trait `for<'b> Trait` is not implemented for `&'b S`
66
|
77
= help: the trait `Trait` is implemented for `&'a mut S`
8+
= note: `for<'b> Trait` is implemented for `&'b mut S`, but not for `&'b S`
89
note: required by a bound in `foo`
910
--> $DIR/imm-ref-trait-object-literal-bound-regions.rs:11:20
1011
|

‎src/test/ui/suggestions/mut-ref-reassignment.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | opt = None;
88
|
99
= note: expected mutable reference `&mut Option<String>`
1010
found enum `Option<_>`
11-
help: consider dereferencing here to assign to the mutable borrowed piece of memory
11+
help: consider dereferencing here to assign to the mutably borrowed value
1212
|
1313
LL | *opt = None;
1414
| +
@@ -34,7 +34,7 @@ LL | opt = Some(String::new())
3434
|
3535
= note: expected mutable reference `&mut Option<String>`
3636
found enum `Option<String>`
37-
help: consider dereferencing here to assign to the mutable borrowed piece of memory
37+
help: consider dereferencing here to assign to the mutably borrowed value
3838
|
3939
LL | *opt = Some(String::new())
4040
| +
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
let x = std::sync::Mutex::new(1usize);
5+
*x.lock().unwrap() = 2;
6+
//~^ ERROR invalid left-hand side of assignment
7+
*x.lock().unwrap() += 1;
8+
//~^ ERROR binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>`
9+
10+
let mut y = x.lock().unwrap();
11+
*y = 2;
12+
//~^ ERROR mismatched types
13+
*y += 1;
14+
//~^ ERROR binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>`
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
let x = std::sync::Mutex::new(1usize);
5+
x.lock().unwrap() = 2;
6+
//~^ ERROR invalid left-hand side of assignment
7+
x.lock().unwrap() += 1;
8+
//~^ ERROR binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>`
9+
10+
let mut y = x.lock().unwrap();
11+
y = 2;
12+
//~^ ERROR mismatched types
13+
y += 1;
14+
//~^ ERROR binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>`
15+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
error[E0070]: invalid left-hand side of assignment
2+
--> $DIR/assign-non-lval-derefmut.rs:5:23
3+
|
4+
LL | x.lock().unwrap() = 2;
5+
| ----------------- ^
6+
| |
7+
| cannot assign to this expression
8+
|
9+
help: consider dereferencing here to assign to the mutably borrowed value
10+
|
11+
LL | *x.lock().unwrap() = 2;
12+
| +
13+
14+
error[E0368]: binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>`
15+
--> $DIR/assign-non-lval-derefmut.rs:7:5
16+
|
17+
LL | x.lock().unwrap() += 1;
18+
| -----------------^^^^^
19+
| |
20+
| cannot use `+=` on type `MutexGuard<'_, usize>`
21+
|
22+
help: `+=` can be used on `usize`, you can dereference `x.lock().unwrap()`
23+
|
24+
LL | *x.lock().unwrap() += 1;
25+
| +
26+
27+
error[E0308]: mismatched types
28+
--> $DIR/assign-non-lval-derefmut.rs:11:9
29+
|
30+
LL | let mut y = x.lock().unwrap();
31+
| ----------------- expected due to this value
32+
LL | y = 2;
33+
| ^ expected struct `MutexGuard`, found integer
34+
|
35+
= note: expected struct `MutexGuard<'_, usize>`
36+
found type `{integer}`
37+
help: consider dereferencing here to assign to the mutably borrowed value
38+
|
39+
LL | *y = 2;
40+
| +
41+
42+
error[E0368]: binary assignment operation `+=` cannot be applied to type `MutexGuard<'_, usize>`
43+
--> $DIR/assign-non-lval-derefmut.rs:13:5
44+
|
45+
LL | y += 1;
46+
| -^^^^^
47+
| |
48+
| cannot use `+=` on type `MutexGuard<'_, usize>`
49+
|
50+
help: `+=` can be used on `usize`, you can dereference `y`
51+
|
52+
LL | *y += 1;
53+
| +
54+
55+
error: aborting due to 4 previous errors
56+
57+
Some errors have detailed explanations: E0070, E0308, E0368.
58+
For more information about an error, try `rustc --explain E0070`.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
let mut x = vec![1usize];
5+
*x.last_mut().unwrap() = 2;
6+
//~^ ERROR invalid left-hand side of assignment
7+
*x.last_mut().unwrap() += 1;
8+
//~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize`
9+
10+
let y = x.last_mut().unwrap();
11+
*y = 2;
12+
//~^ ERROR mismatched types
13+
*y += 1;
14+
//~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize`
15+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
let mut x = vec![1usize];
5+
x.last_mut().unwrap() = 2;
6+
//~^ ERROR invalid left-hand side of assignment
7+
x.last_mut().unwrap() += 1;
8+
//~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize`
9+
10+
let y = x.last_mut().unwrap();
11+
y = 2;
12+
//~^ ERROR mismatched types
13+
y += 1;
14+
//~^ ERROR binary assignment operation `+=` cannot be applied to type `&mut usize`
15+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
error[E0070]: invalid left-hand side of assignment
2+
--> $DIR/assign-non-lval-mut-ref.rs:5:27
3+
|
4+
LL | x.last_mut().unwrap() = 2;
5+
| --------------------- ^
6+
| |
7+
| cannot assign to this expression
8+
|
9+
help: consider dereferencing here to assign to the mutably borrowed value
10+
|
11+
LL | *x.last_mut().unwrap() = 2;
12+
| +
13+
14+
error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut usize`
15+
--> $DIR/assign-non-lval-mut-ref.rs:7:5
16+
|
17+
LL | x.last_mut().unwrap() += 1;
18+
| ---------------------^^^^^
19+
| |
20+
| cannot use `+=` on type `&mut usize`
21+
|
22+
help: `+=` can be used on `usize`, you can dereference `x.last_mut().unwrap()`
23+
|
24+
LL | *x.last_mut().unwrap() += 1;
25+
| +
26+
27+
error[E0308]: mismatched types
28+
--> $DIR/assign-non-lval-mut-ref.rs:11:9
29+
|
30+
LL | let y = x.last_mut().unwrap();
31+
| --------------------- expected due to this value
32+
LL | y = 2;
33+
| ^ expected `&mut usize`, found integer
34+
|
35+
help: consider dereferencing here to assign to the mutably borrowed value
36+
|
37+
LL | *y = 2;
38+
| +
39+
40+
error[E0368]: binary assignment operation `+=` cannot be applied to type `&mut usize`
41+
--> $DIR/assign-non-lval-mut-ref.rs:13:5
42+
|
43+
LL | y += 1;
44+
| -^^^^^
45+
| |
46+
| cannot use `+=` on type `&mut usize`
47+
|
48+
help: `+=` can be used on `usize`, you can dereference `y`
49+
|
50+
LL | *y += 1;
51+
| +
52+
53+
error: aborting due to 4 previous errors
54+
55+
Some errors have detailed explanations: E0070, E0308, E0368.
56+
For more information about an error, try `rustc --explain E0070`.

‎src/test/ui/typeck/issue-93486.stderr

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | vec![].last_mut().unwrap() = 3_u8;
55
| -------------------------- ^
66
| |
77
| cannot assign to this expression
8+
|
9+
help: consider dereferencing here to assign to the mutably borrowed value
10+
|
11+
LL | *vec![].last_mut().unwrap() = 3_u8;
12+
| +
813

914
error: aborting due to previous error
1015

0 commit comments

Comments
 (0)
Please sign in to comment.